mirror of
https://github.com/qi4L/JYso.git
synced 2026-09-21 22:40:43 +08:00
fix: ldaps重构
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
// 忽略关闭异常
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user