From e09b7210bd3021a5a4190588968d3d46bf2f516c Mon Sep 17 00:00:00 2001 From: qi4l Date: Mon, 30 Mar 2026 16:16:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20ldaps=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/qi4l/JYso/LdapsServer.java | 59 ++++++ src/main/java/com/qi4l/JYso/TLSProxy.java | 183 ------------------ .../com/qi4l/JYso/gadgets/Config/Config.java | 4 +- 3 files changed, 60 insertions(+), 186 deletions(-) create mode 100644 src/main/java/com/qi4l/JYso/LdapsServer.java delete mode 100644 src/main/java/com/qi4l/JYso/TLSProxy.java diff --git a/src/main/java/com/qi4l/JYso/LdapsServer.java b/src/main/java/com/qi4l/JYso/LdapsServer.java new file mode 100644 index 0000000..d823703 --- /dev/null +++ b/src/main/java/com/qi4l/JYso/LdapsServer.java @@ -0,0 +1,59 @@ +package com.qi4l.JYso; + +import com.qi4l.JYso.gadgets.Config.Config; +import com.unboundid.ldap.listener.InMemoryDirectoryServer; +import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; +import com.unboundid.ldap.listener.InMemoryListenerConfig; +import com.unboundid.util.ssl.KeyStoreKeyManager; +import com.unboundid.util.ssl.SSLUtil; +import com.unboundid.util.ssl.TrustAllTrustManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.fusesource.jansi.Ansi.ansi; + +public class LdapsServer { + private static final Logger log = LoggerFactory.getLogger(LdapsServer.class); + private final String certFile; + private final String keyPass; + + public LdapsServer(String certFile, String keyPass) { + this.certFile = certFile; + this.keyPass = keyPass; + } + + public static void start() { + System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "...")); + new LdapsServer(Config.certFile, Config.keyPass).run(); + } + + public void run() { + // 设置JDK信任证书 + System.setProperty("javax.net.ssl.trustStore", certFile); + System.setProperty("javax.net.ssl.trustStorePassword", keyPass); + + try { + SSLUtil serverSSLUtil = new SSLUtil( + new KeyStoreKeyManager(certFile, keyPass.toCharArray()), + new TrustAllTrustManager() + ); + SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager()); + + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com"); + config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig( + "listen-ldaps", + null, + Integer.parseInt(String.valueOf(Config.ldapsPort)), + serverSSLUtil.createSSLServerSocketFactory(), + clientSSLUtil.createSSLSocketFactory() + )); + config.addInMemoryOperationInterceptor(new LdapServer()); + + InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); + ds.startListening(); + System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "...")); + } catch (Exception e) { + log.error("e: ", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/qi4l/JYso/TLSProxy.java b/src/main/java/com/qi4l/JYso/TLSProxy.java deleted file mode 100644 index f48b6c7..0000000 --- a/src/main/java/com/qi4l/JYso/TLSProxy.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.qi4l.JYso; - -import com.qi4l.JYso.gadgets.Config.Config; - -import javax.net.ssl.*; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.fusesource.jansi.Ansi.ansi; - -public class TLSProxy { - private final String localAddr; - private final String remoteAddr; - private final String certFile; - private final String keyPass; - - public TLSProxy(String localAddr, String remoteAddr, String certFile, String keyPass) { - this.localAddr = localAddr; - this.remoteAddr = remoteAddr; - this.certFile = certFile; - this.keyPass = keyPass; - } - - public static void start() { - System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.TLSPort + "...")); - new TLSProxy(Config.ip + ":" + Config.TLSPort, Config.ip + ":" + Config.ldapsPort, Config.certFile, Config.keyPass).run(); - } - - public void run() { - // 设置JDK信任证书 - System.setProperty("javax.net.ssl.trustStore", certFile); - System.setProperty("javax.net.ssl.trustStorePassword", keyPass); - - SSLServerSocketFactory sslServerSocketFactory = createSSLServerSocketFactory(); - if (sslServerSocketFactory == null) { - System.err.println("Failed to create SSLServerSocketFactory"); - return; - } - - try (SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket()) { - String[] addressParts = localAddr.split(":"); - serverSocket.bind(new InetSocketAddress(addressParts[0], Integer.parseInt(addressParts[1]))); - - ExecutorService executorService = Executors.newCachedThreadPool(); - while (true) { - SSLSocket clientSocket = (SSLSocket) serverSocket.accept(); - executorService.submit(() -> handleConnection(clientSocket)); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - private SSLServerSocketFactory createSSLServerSocketFactory() { - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - KeyStore keyStore = KeyStore.getInstance("JKS"); - - try (InputStream keyInput = Files.newInputStream(Paths.get(certFile))) { - keyStore.load(keyInput, keyPass.toCharArray()); - } - - keyManagerFactory.init(keyStore, keyPass.toCharArray()); - sslContext.init(keyManagerFactory.getKeyManagers(), null, null); - return sslContext.getServerSocketFactory(); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - private void handleConnection(SSLSocket clientSocket) { - String[] remoteAddressParts = remoteAddr.split(":"); - Socket remoteSocket = null; - - try { - // 修复:使用 remoteAddr 而不是 localAddr - remoteSocket = new Socket(remoteAddressParts[0], Integer.parseInt(remoteAddressParts[1])); - - ExecutorService executorService = Executors.newCachedThreadPool(); - - // 使用标志跟踪连接状态 - final boolean[] connectionClosed = {false}; - - Socket finalRemoteSocket1 = remoteSocket; - executorService.submit(() -> { - try { - forwardData(clientSocket.getInputStream(), finalRemoteSocket1.getOutputStream()); - } catch (IOException e) { - // 正常关闭连接时可能会抛出异常,不打印堆栈跟踪 - if (!connectionClosed[0]) { - System.err.println("Client to remote error: " + e.getMessage()); - } - } finally { - closeConnection(clientSocket, finalRemoteSocket1, connectionClosed); - } - }); - - Socket finalRemoteSocket = remoteSocket; - executorService.submit(() -> { - try { - forwardData(finalRemoteSocket.getInputStream(), clientSocket.getOutputStream()); - } catch (IOException e) { - // 正常关闭连接时可能会抛出异常,不打印堆栈跟踪 - if (!connectionClosed[0]) { - System.err.println("Remote to client error: " + e.getMessage()); - } - } finally { - closeConnection(clientSocket, finalRemoteSocket, connectionClosed); - } - }); - - } catch (IOException e) { - System.err.println("Connection error: " + e.getMessage()); - if (remoteSocket != null) { - try { - remoteSocket.close(); - } catch (IOException ex) { - // 忽略关闭异常 - } - } - try { - clientSocket.close(); - } catch (IOException ex) { - // 忽略关闭异常 - } - } - } - - private void forwardData(InputStream input, OutputStream output) throws IOException { - byte[] buffer = new byte[8192]; - int bytesRead; - - try { - while ((bytesRead = input.read(buffer)) != -1) { - output.write(buffer, 0, bytesRead); - output.flush(); - } - } finally { - // 当读取结束时,关闭输出流 - try { - output.close(); - } catch (IOException e) { - // 忽略关闭异常 - } - } - } - - private void closeConnection(SSLSocket clientSocket, Socket remoteSocket, boolean[] connectionClosed) { - // 使用标志确保连接只关闭一次 - if (connectionClosed[0]) { - return; - } - connectionClosed[0] = true; - - // 关闭远程连接 - if (remoteSocket != null && !remoteSocket.isClosed()) { - try { - remoteSocket.close(); - } catch (IOException e) { - // 忽略关闭异常 - } - } - - // 关闭客户端连接 - if (clientSocket != null && !clientSocket.isClosed()) { - try { - clientSocket.close(); - } catch (IOException e) { - // 忽略关闭异常 - } - } - } -} \ No newline at end of file diff --git a/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java b/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java index b59b3bd..71fdfd3 100644 --- a/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java +++ b/src/main/java/com/qi4l/JYso/gadgets/Config/Config.java @@ -41,10 +41,8 @@ public class Config { public static String USER = ""; @Parameter(names = {"-p", " --PASSWD"}, help = true, description = "ldap binding password", order = 5) public static String PASSWD = ""; - @Parameter(names = {"-t", " --TLSProxy"}, help = true, description = "TLS port forwarding", order = 5) + @Parameter(names = {"-t", " --LdapsServer"}, help = true, description = "TLS port forwarding", order = 5) public static boolean TLSProxy = false; - @Parameter(names = {"-tP", " --TLSPort"}, help = true, description = "TLS port", order = 5) - public static String TLSPort = "1636"; @Parameter(names = {"-kP", " --keyPass"}, help = true, description = "JKS key password", order = 5) public static String keyPass = ""; @Parameter(names = {"-cF", " --certFile"}, help = true, description = "JKS certificate file Path", order = 5)