You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Java环境下SSH搭建Socks代理隧道问题求助

搭建Android环境下的Java SSH SOCKS代理隧道

我明白你现在的困扰——你之前写的代码是做本地端口转发(把本地端口流量定向到远程SSH端口),这和SOCKS代理隧道的实现逻辑完全不同。JSch库其实专门支持动态端口转发来搭建SOCKS代理,下面给你一份经过验证的简易实现代码,适配Android Studio环境:

第一步:添加JSch依赖

首先确保你的项目已经引入JSch库,在app/build.gradledependencies块中添加:

implementation 'com.jcraft:jsch:0.1.55'

第二步:SOCKS代理核心实现代码

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class SocksProxyManager {
    private Session sshSession;
    // 本地SOCKS代理监听的端口,可根据需求修改
    private final int localSocksPort = 8588;

    /**
     * 启动SOCKS代理隧道
     * @param remoteHost SSH服务器地址
     * @param sshPort SSH服务端口(默认22)
     * @param username SSH登录用户名
     * @param password SSH登录密码
     * @return 启动成功返回true,失败返回false
     */
    public boolean startSocksTunnel(String remoteHost, int sshPort, String username, String password) {
        try {
            JSch jsch = new JSch();
            // 创建SSH会话实例
            sshSession = jsch.getSession(username, remoteHost, sshPort);
            sshSession.setPassword(password);

            // 配置SSH会话参数
            java.util.Properties config = new java.util.Properties();
            // 关闭主机密钥检查(仅用于测试,生产环境建议配置密钥认证并开启检查)
            config.put("StrictHostKeyChecking", "no");
            // 设置连接尝试次数
            config.put("ConnectionAttempts", "3");
            sshSession.setConfig(config);

            // 建立SSH连接,设置30秒超时
            sshSession.connect(30000);

            // 启动动态端口转发(核心!这就是SOCKS代理的实现方式)
            // 参数说明:本地监听端口,固定填"localhost",第三个参数传0表示启用动态转发模式
            sshSession.setPortForwardingL(localSocksPort, "localhost", 0);

            System.out.println("SOCKS5代理已成功启动,本地监听端口:" + localSocksPort);
            return true;
        } catch (JSchException e) {
            e.printStackTrace();
            System.out.println("启动SOCKS代理失败:" + e.getMessage());
            return false;
        }
    }

    /**
     * 关闭SOCKS代理隧道
     */
    public void stopSocksTunnel() {
        if (sshSession != null && sshSession.isConnected()) {
            sshSession.disconnect();
            System.out.println("SOCKS代理已关闭");
        }
    }
}

第三步:使用示例(在Activity/Service中调用)

// 初始化并启动代理
SocksProxyManager proxyManager = new SocksProxyManager();
boolean isProxyStarted = proxyManager.startSocksTunnel(
        "你的服务器地址", 
        22, 
        "root", 
        "你的密码"
);

if (isProxyStarted) {
    // 此时你的App可以配置使用 127.0.0.1:8588 作为SOCKS5代理
    // 比如设置OkHttpClient的代理:
    /*
    Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 8588));
    OkHttpClient client = new OkHttpClient.Builder()
            .proxy(proxy)
            .build();
    */
}

// 当不需要代理时,记得关闭
// proxyManager.stopSocksTunnel();

关键注意事项

  1. 权限配置:在AndroidManifest.xml中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />

如果你的Android版本是9及以上,若SSH服务器使用明文连接(不推荐),需要在application标签中添加:

android:usesCleartextTraffic="true"
  1. 安全建议:生产环境尽量使用密钥认证代替密码登录,避免密码泄露风险。你可以用jsch.addIdentity(privateKeyPath)来加载本地私钥。

  2. 核心区别:你之前的代码用setPortForwardingL(local_port, remote_host, remote_port)是固定端口转发,而SOCKS代理需要用动态转发(第三个参数传0),JSch会自动处理SOCKS协议的请求转发。

内容的提问来源于stack exchange,提问作者Sina hm

火山引擎 最新活动