optimizer: 服务器证书维护新增删除

This commit is contained in:
suxiang
2024-09-17 14:57:57 +08:00
parent ee08bc6ed3
commit b08bef691f
3 changed files with 30 additions and 66 deletions
@@ -1,7 +1,6 @@
package org.dromara.neutrinoproxy.server.proxy.enhance;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
@@ -9,9 +8,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SniHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslHandler;
import lombok.extern.slf4j.Slf4j;
import org.dromara.neutrinoproxy.core.util.FileUtil;
import org.dromara.neutrinoproxy.server.base.proxy.ProxyConfig;
import org.dromara.neutrinoproxy.server.proxy.core.BytesMetricsHandler;
import org.dromara.neutrinoproxy.server.proxy.security.HttpVisitorSecurityChannelHandler;
@@ -21,13 +18,6 @@ import org.noear.solon.annotation.Inject;
import org.noear.solon.core.event.AppLoadEndEvent;
import org.noear.solon.core.event.EventListener;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import java.io.InputStream;
import java.security.KeyStore;
/**
* HTTPS代理
* @author: aoshiguchen
@@ -70,32 +60,6 @@ public class HttpsProxy implements EventListener<AppLoadEndEvent> {
}
}
private ChannelHandler createSslHandler() {
try {
InputStream jksInputStream = FileUtil.getInputStream(proxyConfig.getServer().getTcp().getJksPath());
SSLContext serverContext = SSLContext.getInstance("TLS");
final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(jksInputStream, proxyConfig.getServer().getTcp().getKeyStorePassword().toCharArray());
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, proxyConfig.getServer().getTcp().getKeyStorePassword().toCharArray());
TrustManager[] trustManagers = null;
serverContext.init(kmf.getKeyManagers(), trustManagers, null);
SSLEngine sslEngine = serverContext.createSSLEngine();
sslEngine.setUseClientMode(false);
sslEngine.setNeedClientAuth(false);
return new SslHandler(sslEngine);
} catch (Exception e) {
log.error("create SSL handler failed", e);
e.printStackTrace();
}
return null;
}
public SniHandler createSniHandler() {
try {
return new SniHandler(domainName -> {
@@ -103,7 +67,8 @@ public class HttpsProxy implements EventListener<AppLoadEndEvent> {
if (sslContext != null) {
return sslContext;
} else {
throw new IllegalArgumentException("No SSL context available for domain: " + domainName);
log.info("No SSL context available for domain: {}", domainName);
return null;
}
});
} catch (Exception e) {
@@ -1,31 +1,20 @@
package org.dromara.neutrinoproxy.server.proxy.enhance;
import ch.qos.logback.core.net.ssl.SSL;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SniHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.DomainWildcardMappingBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.solon.annotation.Db;
import org.dromara.neutrinoproxy.core.util.FileUtil;
import org.dromara.neutrinoproxy.server.base.proxy.ProxyConfig;
import org.dromara.neutrinoproxy.server.dal.DomainMapper;
import org.dromara.neutrinoproxy.server.dal.entity.DomainNameDO;
import org.dromara.neutrinoproxy.server.util.ProxyUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Http;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.List;
@@ -58,23 +47,6 @@ public class SslContextManager {
}
}
// 使用 JKS 文件加载 SSL 上下文,禁用客户端认证并设置为服务器模式
private SslContext loadSslContextFromJks(byte[] jks, String keyStorePassword) throws Exception {
InputStream jksInputStream = new ByteArrayInputStream(jks);
// 初始化 KeyStore
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(jksInputStream, keyStorePassword.toCharArray());
// 初始化 KeyManagerFactory
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyStorePassword.toCharArray());
// 创建 SslContext 并禁用客户端认证
return SslContextBuilder.forServer(kmf)
.clientAuth(ClientAuth.NONE) // 禁用客户端认证
.build();
}
// 初始化所有域名的 SSL 上下文
private void initializeSslContexts() throws Exception {
List<DomainNameDO> domainNameDOS = domainMapper.selectList(Wrappers.<DomainNameDO>lambdaQuery()
@@ -99,10 +71,32 @@ public class SslContextManager {
domainSslContexts.put(domain, sslContext);
}
// 使用 JKS 文件加载 SSL 上下文,禁用客户端认证并设置为服务器模式
private SslContext loadSslContextFromJks(byte[] jks, String keyStorePassword) throws Exception {
InputStream jksInputStream = new ByteArrayInputStream(jks);
// 初始化 KeyStore
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(jksInputStream, keyStorePassword.toCharArray());
// 初始化 KeyManagerFactory
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyStorePassword.toCharArray());
// 创建 SslContext 并禁用客户端认证
return SslContextBuilder.forServer(kmf)
.clientAuth(ClientAuth.NONE) // 禁用客户端认证
.build();
}
public SslContext getSslContextByDomain(String domain) {
return domainSslContexts.get(domain);
}
public void removeSslContextByDomain(String domain) {
domainSslContexts.remove(domain);
}
public SslContext getSslContextByFullDomain(String fullDomain) {
String domain = ProxyUtil.getDomainNameByFullDomain(fullDomain);
return domainSslContexts.get(domain);
@@ -172,8 +172,11 @@ public class DomainService {
byte[] byteArray = toByteArray(content);
updateWrapper.set(DomainNameDO::getKeyStorePassword, req.getKeyStorePassword());
updateWrapper.set(DomainNameDO::getJks, byteArray);
//添加证书
//添加证书并删除旧的证书
sslContextManager.addDomainAndCert(req.getDomain(), byteArray, req.getKeyStorePassword());
if (!req.getDomain().equals(oldDomainNameDO.getDomain())) {
sslContextManager.removeSslContextByDomain(oldDomainNameDO.getDomain());
}
} catch (Exception e) {
log.error("证书添加失败", e);
e.printStackTrace();
@@ -225,6 +228,8 @@ public class DomainService {
ProxyUtil.removeDomainToDomainNameId(domainNameDO.getDomain());
}
domainMapper.deleteById(domainNameId);
//删除证书
sslContextManager.removeSslContextByDomain(domainNameDO.getDomain());
}
public DomainUpdateDefaultStatusRes updateDefaultStatus(Integer id, Integer isDefault) {