lvzhiqiang 2 сар өмнө
parent
commit
6a8b48c68d

+ 13 - 0
pom.xml

@@ -198,6 +198,19 @@
             <artifactId>xxl-job-core</artifactId>
             <version>2.3.1</version>
         </dependency>
+
+        <!--Java内置SSH隧道(JSch库)-->
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId>
+            <version>0.1.55</version>
+        </dependency>
+        <!-- JSch依赖BouncyCastle用于加密 -->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.70</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 72 - 0
src/main/java/top/lvzhiqiang/util/JsoupWithSshTunnel.java

@@ -0,0 +1,72 @@
+package top.lvzhiqiang.util;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+
+public class JsoupWithSshTunnel {
+    private static final String REMOTE_HOST = "144.34.207.84";  // 远程Trojan服务器IP/域名
+    private static final int REMOTE_PORT = 26376;  // SSH端口,通常22
+    private static final String USERNAME = "root";
+    private static final String PASSWORD = "SnS2fm42wWWc";  // 或用私钥
+    private static final int LOCAL_SOCKS_PORT = 1235;  // 本地SOCKS5端口
+
+    private Session sshSession;
+
+    // 初始化SSH隧道
+    public void initTunnel() throws Exception {
+        JSch jsch = new JSch();
+        // 如果用私钥:jsch.addIdentity("/path/to/private-key");
+        sshSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
+        sshSession.setPassword(PASSWORD);
+        sshSession.setConfig("StrictHostKeyChecking", "no");  // 跳过主机密钥检查(生产环境慎用)
+        sshSession.connect(30000);  // 连接超时30秒
+
+        // 设置动态端口转发(SOCKS5)
+        // 注意:这里"127.0.0.1", 0 表示动态转发到远程的任意端口
+        sshSession.setPortForwardingL(LOCAL_SOCKS_PORT, "127.0.0.1", 0);  // 简化版动态转发
+        System.out.println("SSH隧道建立成功,本地SOCKS5代理: 127.0.0.1:" + LOCAL_SOCKS_PORT);
+    }
+
+    // 使用Jsoup爬取(通过隧道代理)
+    public Document fetchWithProxy(String url) throws Exception {
+        Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", LOCAL_SOCKS_PORT));
+        proxy = Proxy.NO_PROXY;
+
+        return Jsoup.connect(url)
+                .proxy(proxy)
+                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
+                .timeout(10000)
+                .get();
+    }
+
+    // 关闭隧道
+    public void closeTunnel() {
+        if (sshSession != null && sshSession.isConnected()) {
+            sshSession.disconnect();
+            System.out.println("SSH隧道已关闭");
+        }
+    }
+
+    public static void main(String[] args) {
+        JsoupWithSshTunnel app = new JsoupWithSshTunnel();
+        try {
+            app.initTunnel();  // 先建隧道
+
+            // 爬取示例
+            Document doc = app.fetchWithProxy("https://www.baidu.com");
+            System.out.println("Title: " + doc.title());
+
+            // 你的业务逻辑...
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            app.closeTunnel();  // 结束后关闭
+        }
+    }
+}

+ 87 - 0
src/main/java/top/lvzhiqiang/util/SSHDynamicProxy.java

@@ -0,0 +1,87 @@
+package top.lvzhiqiang.util;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import org.jsoup.Connection;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+
+public class SSHDynamicProxy {
+    private JSch jsch;
+    private Session session;
+    private final int localPort = 1111;  // 本地 SOCKS5 端口
+
+    /**
+     * SSH 服务器参数:host/user/password 是 SSH 登录凭据
+     */
+    public void startDynamicProxy(String sshHost, int sshPort, String sshUser, String sshPassword) throws Exception {
+        jsch = new JSch();
+
+        // 创建 SSH 会话
+        session = jsch.getSession(sshUser, sshHost, sshPort);  // sshPort 默认为 22
+        session.setPassword(sshPassword);  // SSH 登录密码,不是 Trojan 密码
+
+        // 配置:跳过主机密钥检查(生产环境不推荐)
+        java.util.Properties config = new java.util.Properties();
+        config.put("StrictHostKeyChecking", "no");
+        session.setConfig(config);
+
+        // 建立连接
+        session.connect();
+        System.out.println("SSH 连接成功: " + sshHost);
+
+        // 建立动态端口转发(SOCKS5 代理)
+        int assignedPort = session.setPortForwardingL(localPort, "0.0.0.0", 0);
+        System.out.println("SOCKS5 代理启动在: 127.0.0.1:" + assignedPort);
+    }
+
+    /**
+     * 通过 SSH 隧道爬取网页
+     */
+    public Document fetchViaSSH(String targetUrl) throws Exception {
+        // 创建 SOCKS5 代理,指向本地端口
+        Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", localPort));
+
+        Connection connection = Jsoup.connect(targetUrl)
+                .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
+                .proxy(proxy)  // 使用本地 SOCKS5 代理
+                .timeout(30000)
+                .followRedirects(true);
+
+        Document doc = connection.get();
+        System.out.println("页面标题: " + doc.title());
+        return doc;
+    }
+
+    public void stop() {
+        if (session != null && session.isConnected()) {
+            session.disconnect();
+            System.out.println("SSH 连接已断开");
+        }
+    }
+
+    public static void main(String[] args) {
+        SSHDynamicProxy proxy = new SSHDynamicProxy();
+        try {
+            // SSH 服务器配置(不是 Trojan 配置)
+            String sshHost = "144.34.207.84";  // SSH 服务器 IP/域名
+            String sshUser = "root";                 // SSH 用户名
+            String sshPassword = "SnS2fm42wWWc"; // SSH 登录密码
+
+            // 启动 SSH 动态代理
+            proxy.startDynamicProxy(sshHost, 26376, sshUser, sshPassword);
+
+            // 测试访问(通过 SSH 隧道)
+            Document doc = proxy.fetchViaSSH("https://www.google.com");
+            System.out.println("IP 检查: " + doc.select("pre").text()); // 应显示 SSH 服务器 IP
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            proxy.stop();
+        }
+    }
+}