diff --git a/proxy-client/src/main/java/org/fengfei/lanproxy/client/SslContextCreator.java b/proxy-client/src/main/java/org/fengfei/lanproxy/client/SslContextCreator.java index f5d66f2d..5e887a25 100644 --- a/proxy-client/src/main/java/org/fengfei/lanproxy/client/SslContextCreator.java +++ b/proxy-client/src/main/java/org/fengfei/lanproxy/client/SslContextCreator.java @@ -6,12 +6,10 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; +import java.security.*; import java.security.cert.CertificateException; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; @@ -31,8 +29,9 @@ public static SSLContext createSSLContext() { public SSLContext initSSLContext() { logger.info("Checking SSL configuration properties..."); final String jksPath = Config.getInstance().getStringValue("ssl.jksPath"); - logger.info("Initializing SSL context. KeystorePath = {}.", jksPath); - if (jksPath == null || jksPath.isEmpty()) { + final String caPath = Config.getInstance().getStringValue("ssl.TrustkeyStorePath"); + logger.info("Initializing SSL context. KeystorePath = {}.{}", jksPath,caPath); + if (jksPath == null || jksPath.isEmpty() ||caPath == null || caPath.isEmpty()) { // key_store_password or key_manager_password are empty logger.warn("The keystore path is null or empty. The SSL context won't be initialized."); return null; @@ -48,22 +47,29 @@ public SSLContext initSSLContext() { try { logger.info("Loading keystore. KeystorePath = {}.", jksPath); InputStream jksInputStream = jksDatastore(jksPath); + InputStream caInputStream = jksDatastore(caPath); SSLContext clientSSLContext = SSLContext.getInstance("TLS"); - final KeyStore ks = KeyStore.getInstance("JKS"); + final KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(jksInputStream, keyStorePassword.toCharArray()); + final KeyStore caks = KeyStore.getInstance("JKS"); + caks.load(caInputStream, keyStorePassword.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, keyStorePassword.toCharArray()); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); + tmf.init(caks); TrustManager[] trustManagers = tmf.getTrustManagers(); // init sslContext logger.info("Initializing SSL context..."); - clientSSLContext.init(null, trustManagers, null); + clientSSLContext.init(kmf.getKeyManagers(), trustManagers, null); logger.info("The SSL context has been initialized successfully."); return clientSSLContext; - } catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException - | IOException ex) { + } catch (NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | KeyStoreException + | KeyManagementException | IOException ex) { logger.error("Unable to initialize SSL context. Cause = {}, errorMessage = {}.", ex.getCause(), ex.getMessage()); return null; diff --git a/proxy-client/src/main/resources/RootCA.jks b/proxy-client/src/main/resources/RootCA.jks new file mode 100644 index 00000000..6b59a6be Binary files /dev/null and b/proxy-client/src/main/resources/RootCA.jks differ diff --git a/proxy-client/src/main/resources/config.properties b/proxy-client/src/main/resources/config.properties index b48b6e2f..0f242d55 100644 --- a/proxy-client/src/main/resources/config.properties +++ b/proxy-client/src/main/resources/config.properties @@ -1,9 +1,10 @@ -client.key=client -ssl.enable=false -ssl.jksPath=test.jks +client.key=6e9a51ca84ac465a82b0e0182285fe59 +ssl.enable=true +ssl.jksPath=lanproxyClient.pfx +ssl.TrustkeyStorePath=RootCA.jks ssl.keyStorePassword=123456 -server.host=127.0.0.1 +server.host=180.102.133.252 #default ssl port is 4993 -server.port=4900 \ No newline at end of file +server.port=4993 \ No newline at end of file diff --git a/proxy-client/src/main/resources/lanproxyClient.pfx b/proxy-client/src/main/resources/lanproxyClient.pfx new file mode 100644 index 00000000..2ec8fd9b Binary files /dev/null and b/proxy-client/src/main/resources/lanproxyClient.pfx differ diff --git a/proxy-client/src/main/resources/test.jks b/proxy-client/src/main/resources/test.jks deleted file mode 100644 index 08cfafa3..00000000 Binary files a/proxy-client/src/main/resources/test.jks and /dev/null differ diff --git a/proxy-server/src/main/java/org/fengfei/lanproxy/server/ProxyChannelManager.java b/proxy-server/src/main/java/org/fengfei/lanproxy/server/ProxyChannelManager.java index d50150d4..32ccace1 100644 --- a/proxy-server/src/main/java/org/fengfei/lanproxy/server/ProxyChannelManager.java +++ b/proxy-server/src/main/java/org/fengfei/lanproxy/server/ProxyChannelManager.java @@ -65,6 +65,8 @@ public synchronized void onChanged() { List inetPorts = new ArrayList(ProxyConfig.getInstance().getClientInetPorts(clientKey)); Set inetPortSet = new HashSet(inetPorts); List channelInetPorts = new ArrayList(proxyChannel.attr(CHANNEL_PORT).get()); + ProxyConfig.Client cli = ProxyConfig.getInstance().getClients(clientKey); + if(cli == null) continue; synchronized (portCmdChannelMapping) { @@ -77,7 +79,7 @@ public synchronized void onChanged() { // 判断是否是同一个连接对象,有可能之前已经更换成其他client的连接了 if (proxyChannel == channel) { - if (!inetPortSet.contains(chanelInetPort)) { + if (!inetPortSet.contains(chanelInetPort) || !cli.isProxyEnable(chanelInetPort)) { // 移除新配置中不包含的端口 portCmdChannelMapping.remove(chanelInetPort); @@ -92,8 +94,10 @@ public synchronized void onChanged() { // 将新配置中增加的外网端口写入到映射配置中 for (int inetPort : inetPorts) { - portCmdChannelMapping.put(inetPort, proxyChannel); - proxyChannel.attr(CHANNEL_PORT).get().add(inetPort); + if(cli.isProxyEnable(inetPort)) { + portCmdChannelMapping.put(inetPort, proxyChannel); + proxyChannel.attr(CHANNEL_PORT).get().add(inetPort); + } } checkAndClearUserChannels(proxyChannel); diff --git a/proxy-server/src/main/java/org/fengfei/lanproxy/server/SslContextCreator.java b/proxy-server/src/main/java/org/fengfei/lanproxy/server/SslContextCreator.java index 644e8267..45e4e80d 100644 --- a/proxy-server/src/main/java/org/fengfei/lanproxy/server/SslContextCreator.java +++ b/proxy-server/src/main/java/org/fengfei/lanproxy/server/SslContextCreator.java @@ -76,8 +76,13 @@ public SSLContext initSSLContext() { // use keystore as truststore, as server needs to trust // certificates signed by the // server certificates + final String caPath = Config.getInstance().getStringValue("server.ssl.TrustkeyStorePath"); + InputStream caInputStream = jksDatastore(caPath); + final KeyStore caks = KeyStore.getInstance("JKS"); + caks.load(caInputStream, keyStorePassword.toCharArray()); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); + tmf.init(caks); trustManagers = tmf.getTrustManagers(); } diff --git a/proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java b/proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java index ef78feeb..7b77ba4a 100644 --- a/proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java +++ b/proxy-server/src/main/java/org/fengfei/lanproxy/server/config/ProxyConfig.java @@ -154,6 +154,13 @@ public List getClients() { return clients; } + public Client getClients(String clientKey) { + for (Client cli: clients) { + if(cli.getClientKey().equals(clientKey))return cli; + } + return null; + } + /** * 解析配置文件 */ @@ -202,7 +209,9 @@ public void update(String proxyMappingConfigJson) { throw new IllegalArgumentException("一个公网端口只能映射一个后端信息,不能重复: " + port); } - inetPortLanInfoMapping.put(port, mapping.getLan()); + if(mapping.getEnable() && client.isProxyEnable(port)) { + inetPortLanInfoMapping.put(port, mapping.getLan()); + } } } @@ -354,6 +363,12 @@ public void setStatus(int status) { this.status = status; } + public Boolean isProxyEnable(int inetPort) { + for (ClientProxyMapping cli:proxyMappings) { + if(cli.getInetPort() == inetPort) return cli.getEnable(); + } + return false; + } } /** @@ -373,6 +388,9 @@ public static class ClientProxyMapping { /** 备注名称 */ private String name; + /** 是否启用 */ + private Boolean enable; + public Integer getInetPort() { return inetPort; } @@ -397,6 +415,13 @@ public void setName(String name) { this.name = name; } + public Boolean getEnable() { + return enable; + } + + public void setEnable(Boolean enable) { + this.enable = enable; + } } /** diff --git a/proxy-server/src/main/resources/config.properties b/proxy-server/src/main/resources/config.properties index 00d35180..807b17c2 100644 --- a/proxy-server/src/main/resources/config.properties +++ b/proxy-server/src/main/resources/config.properties @@ -4,12 +4,13 @@ server.port=4900 server.ssl.enable=true server.ssl.bind=0.0.0.0 server.ssl.port=4993 -server.ssl.jksPath=test.jks +server.ssl.jksPath=lanproxyServer.pfx +server.ssl.TrustkeyStorePath=RootCA.jks server.ssl.keyStorePassword=123456 server.ssl.keyManagerPassword=123456 server.ssl.needsClientAuth=false config.server.bind=0.0.0.0 -config.server.port=8090 +config.server.port=9090 config.admin.username=admin -config.admin.password=admin \ No newline at end of file +config.admin.password=Abs@15732 \ No newline at end of file diff --git a/proxy-server/src/main/resources/test.jks b/proxy-server/src/main/resources/test.jks deleted file mode 100644 index 08cfafa3..00000000 Binary files a/proxy-server/src/main/resources/test.jks and /dev/null differ diff --git a/proxy-server/webpages/i18n/lang_zh_CN.properties b/proxy-server/webpages/i18n/lang_zh_CN.properties index 4e687a5c..718f577c 100644 --- a/proxy-server/webpages/i18n/lang_zh_CN.properties +++ b/proxy-server/webpages/i18n/lang_zh_CN.properties @@ -21,6 +21,8 @@ public.back=返回 public.notice.updatesuccess=更新成功 public.notice.addsuccess=添加成功 public.tips=提示 +public.enable=启用 +public.disable=禁用 client.list=客户端列表 client.name=客户端名称 @@ -44,6 +46,7 @@ lan.name=代理名称 lan.inetport=公网端口 lan.inetport.placeholder=请输入公网出口端口,请确保端口没有被其他程序占用 lan.ip=后端IP端口 +lan.enable=是否开启 lan.ip.placeholder=请输入后端代理信息,格式:127.0.0.1:80 lan.notice.inputname=请输入代理信息备注名称 lan.notice.inputinetport=请输入公网出口端口 diff --git a/proxy-server/webpages/lanproxy-config/html/lan/add.html b/proxy-server/webpages/lanproxy-config/html/lan/add.html index 2f8fa2fe..d1f7118e 100644 --- a/proxy-server/webpages/lanproxy-config/html/lan/add.html +++ b/proxy-server/webpages/lanproxy-config/html/lan/add.html @@ -63,7 +63,8 @@ clientList[clientIndex].proxyMappings.push({ name:name, inetPort:inetPort, - lan:lan + lan:lan, + enable:true }); api_invoke("/config/update", clientList, function(data) { diff --git a/proxy-server/webpages/lanproxy-config/html/lan/edit.html b/proxy-server/webpages/lanproxy-config/html/lan/edit.html index 8c223a56..d90ca093 100644 --- a/proxy-server/webpages/lanproxy-config/html/lan/edit.html +++ b/proxy-server/webpages/lanproxy-config/html/lan/edit.html @@ -2,42 +2,64 @@
-
-
- -
- -
-
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
- -
- -
-
-
- -
- -
-
-
-
- - -
-
-
+ +
+ +
+
+
+
+ + +
+
+ +