From e2f351d898df109a56321740df80384de0e94aa5 Mon Sep 17 00:00:00 2001 From: aoshiguchen <1052045476@qq.com> Date: Mon, 29 Aug 2022 21:13:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=90=86=E9=80=BB=E8=BE=91=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../proxy/client/config/ProxyConfig.java | 2 +- .../proxy/client/core/ProxyClientRunner.java | 29 +++++++-- .../handler/ProxyMessageConnectHandler.java | 2 +- .../asgc/neutrino/proxy/core/Constants.java | 1 + .../proxy/core/ProxyDataTypeEnum.java | 3 +- .../neutrino/proxy/core/ProxyMessage.java | 1 + .../server/base/proxy/ProxyServerConfig.java | 11 ++-- .../proxy/server/dal/LicenseMapper.java | 3 + .../proxy/server/dal/PortMappingMapper.java | 5 ++ .../handler/ProxyMessageAuthHandler.java | 60 ++++++++++++++----- .../proxy/server/service/LicenseService.java | 4 ++ .../server/service/PortMappingService.java | 9 +++ .../proxy/server/service/UserService.java | 4 ++ .../server/util/ProxyChannelManager.java | 2 +- 14 files changed, 108 insertions(+), 28 deletions(-) diff --git a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/config/ProxyConfig.java b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/config/ProxyConfig.java index 2bf10eb4..416f3fb6 100644 --- a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/config/ProxyConfig.java +++ b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/config/ProxyConfig.java @@ -39,7 +39,7 @@ public class ProxyConfig { public static ProxyConfig instance; private Protocol protocol; private Client client; - private ProxyClientConfig clientConfig; + private String licenseKey; @Data public static class Protocol { diff --git a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/core/ProxyClientRunner.java b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/core/ProxyClientRunner.java index cb1d6dd4..fb7b1c05 100644 --- a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/core/ProxyClientRunner.java +++ b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/core/ProxyClientRunner.java @@ -28,6 +28,7 @@ import fun.asgc.neutrino.core.annotation.Bean; import fun.asgc.neutrino.core.annotation.Component; import fun.asgc.neutrino.core.annotation.NonIntercept; import fun.asgc.neutrino.core.context.ApplicationRunner; +import fun.asgc.neutrino.core.util.ArrayUtil; import fun.asgc.neutrino.core.util.CollectionUtil; import fun.asgc.neutrino.core.util.FileUtil; import fun.asgc.neutrino.core.util.StringUtil; @@ -71,8 +72,7 @@ public class ProxyClientRunner implements ApplicationRunner { @Override public void run(String[] args) { - ProxyClientConfig clientConfig = getClientConfig(args.length >= 1 ? args[args.length - 1] : null); - proxyConfig.setClientConfig(clientConfig); + proxyConfig.setLicenseKey(getLicenseKey(args)); connectProxyServer(); } @@ -115,13 +115,13 @@ public class ProxyClientRunner implements ApplicationRunner { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { - // 连接成功,向服务器发送客户端认证信息(clientKey) ClientChannelMannager.setCmdChannel(future.channel()); - future.channel().writeAndFlush(ProxyMessage.buildAuthMessage(JSONObject.toJSONString(proxyConfig.getClientConfig()))); + future.channel().writeAndFlush(ProxyMessage.buildAuthMessage(proxyConfig.getLicenseKey())); log.info("连接代理服务成功."); } else { log.info("连接代理服务失败!"); + System.exit(-1); } } }); @@ -183,4 +183,25 @@ public class ProxyClientRunner implements ApplicationRunner { } return null; } + + private String getLicenseKey(String[] args) { + String license = ""; + if (null != args && ArrayUtil.notEmpty(args)) { + for (String s : args) { + if (s.startsWith("license=") && s.length() > 8) { + license = s.substring(8).trim(); + } + } + } + if (StringUtil.isEmpty(license)) { + license = FileUtil.readContentAsString("./.neutrino-proxy.license"); + } + if (StringUtil.isEmpty(license)) { + log.error("未配置license,执行结束."); + System.exit(-1); + } + FileUtil.write("./.neutrino-proxy.license", license); + + return license; + } } diff --git a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/handler/ProxyMessageConnectHandler.java b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/handler/ProxyMessageConnectHandler.java index f72dbec5..81241155 100644 --- a/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/handler/ProxyMessageConnectHandler.java +++ b/neutrino-proxy-client/src/main/java/fun/asgc/neutrino/proxy/client/handler/ProxyMessageConnectHandler.java @@ -75,7 +75,7 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler { realServerChannel.attr(Constants.NEXT_CHANNEL).set(channel); // 远程绑定 - channel.writeAndFlush(ProxyMessage.buildConnectMessage(userId + "@" + ProxyConfig.instance.getClientConfig().getClientKey())); + channel.writeAndFlush(ProxyMessage.buildConnectMessage(userId + "@" + ProxyConfig.instance.getLicenseKey())); realServerChannel.config().setOption(ChannelOption.AUTO_READ, true); ClientChannelMannager.addRealServerChannel(userId, realServerChannel); diff --git a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/Constants.java b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/Constants.java index 600d6da1..e75a21a8 100644 --- a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/Constants.java +++ b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/Constants.java @@ -50,5 +50,6 @@ public interface Constants { String DISCONNECT = "DISCONNECT"; String TRANSFER = "TRANSFER"; String ERROR = "ERROR"; + String PORT_MAPPING_SYNC = "PORT_MAPPING_SYNC"; } } diff --git a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyDataTypeEnum.java b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyDataTypeEnum.java index c573eac6..059aedb7 100644 --- a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyDataTypeEnum.java +++ b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyDataTypeEnum.java @@ -43,7 +43,8 @@ public enum ProxyDataTypeEnum { CONNECT(0x03, Constants.ProxyDataTypeName.CONNECT,"连接"), DISCONNECT(0x04, Constants.ProxyDataTypeName.DISCONNECT,"断开连接"), TRANSFER(0x05, Constants.ProxyDataTypeName.TRANSFER,"数据传输"), - ERROR(0x06, Constants.ProxyDataTypeName.ERROR,"异常"); + ERROR(0x06, Constants.ProxyDataTypeName.ERROR,"异常"), + PORT_MAPPING_SYNC(0x07, Constants.ProxyDataTypeName.PORT_MAPPING_SYNC, "端口映射同步"); private static Map cache = Stream.of(values()).collect(Collectors.toMap(ProxyDataTypeEnum::getType, Function.identity())); private int type; diff --git a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyMessage.java b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyMessage.java index 96ab24c6..6308df48 100644 --- a/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyMessage.java +++ b/neutrino-proxy-core/src/main/java/fun/asgc/neutrino/proxy/core/ProxyMessage.java @@ -27,6 +27,7 @@ import lombok.Data; import lombok.experimental.Accessors; import java.util.Arrays; +import java.util.List; /** * diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/proxy/ProxyServerConfig.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/proxy/ProxyServerConfig.java index 29caad0c..37d86e86 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/proxy/ProxyServerConfig.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/proxy/ProxyServerConfig.java @@ -23,6 +23,7 @@ package fun.asgc.neutrino.proxy.server.base.proxy; import fun.asgc.neutrino.proxy.core.ProxyClientConfig; +import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO; import lombok.Data; import java.io.Serializable; @@ -52,12 +53,12 @@ public class ProxyServerConfig implements Serializable { */ private volatile Map inetPortLanInfoMapping = new HashMap(); - public void addClientConfig(ProxyClientConfig clientConfig) { - String clientKey = clientConfig.getClientKey(); + public void addClientConfig(String licenseKey, List portMappingList) { + String clientKey = licenseKey; List ports = new ArrayList<>(); - for (ProxyClientConfig.Proxy proxy : clientConfig.getProxy()) { - ports.add(proxy.getServerPort()); - inetPortLanInfoMapping.put(proxy.getServerPort(), proxy.getClientInfo()); + for (PortMappingDO portMapping : portMappingList) { + ports.add(portMapping.getServerPort()); + inetPortLanInfoMapping.put(portMapping.getServerPort(), portMapping.getClientIp() + ":" + portMapping.getClientPort()); } clientInetPortMapping.put(clientKey, ports); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java index 339a16f1..1b87a8c8 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java @@ -89,4 +89,7 @@ public interface LicenseMapper extends SqlMapper { @ResultType(LicenseDO.class) @Select("select * from `license` where user_id = :userId and name =:name and id not in (:excludeIds) limit 0,1") LicenseDO checkRepeat(@Param("userId") Integer userId, @Param("name") String name, @Param("excludeIds") Set excludeIds); + + @Select("select * from `license` where key = ?") + LicenseDO findByKey(String licenseKey); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java index 5b90487e..00558a9c 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java @@ -33,6 +33,7 @@ import fun.asgc.neutrino.proxy.server.controller.req.PortMappingListReq; import fun.asgc.neutrino.proxy.server.controller.res.PortMappingListRes; import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO; +import java.util.List; import java.util.Set; /** @@ -65,4 +66,8 @@ public interface PortMappingMapper extends SqlMapper { @Select("select * from port_mapping where server_port = :port and id not in (:excludeIds)") PortMappingDO findByPort(@Param("port") Integer port, @Param("excludeIds") Set excludeIds); + + @ResultType(PortMappingDO.class) + @Select("select * from port_mapping where license_id = ? and enable = 1") + List findEnableListByLicenseId(Integer licenseId); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/handler/ProxyMessageAuthHandler.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/handler/ProxyMessageAuthHandler.java index 1b381ea8..9c89f303 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/handler/ProxyMessageAuthHandler.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/handler/ProxyMessageAuthHandler.java @@ -22,16 +22,24 @@ package fun.asgc.neutrino.proxy.server.handler; -import com.alibaba.fastjson.JSONObject; import fun.asgc.neutrino.core.annotation.Autowired; import fun.asgc.neutrino.core.annotation.Component; import fun.asgc.neutrino.core.annotation.Match; import fun.asgc.neutrino.core.annotation.NonIntercept; +import fun.asgc.neutrino.core.util.CollectionUtil; +import fun.asgc.neutrino.core.util.StringUtil; import fun.asgc.neutrino.proxy.core.*; import fun.asgc.neutrino.proxy.server.base.proxy.ProxyConfig; import fun.asgc.neutrino.proxy.server.base.proxy.ProxyServerConfig; +import fun.asgc.neutrino.proxy.server.base.rest.constant.EnableStatusEnum; import fun.asgc.neutrino.proxy.server.core.BytesMetricsHandler; import fun.asgc.neutrino.proxy.server.core.UserChannelHandler; +import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO; +import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO; +import fun.asgc.neutrino.proxy.server.dal.entity.UserDO; +import fun.asgc.neutrino.proxy.server.service.LicenseService; +import fun.asgc.neutrino.proxy.server.service.PortMappingService; +import fun.asgc.neutrino.proxy.server.service.UserService; import fun.asgc.neutrino.proxy.server.util.ProxyChannelManager; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -61,37 +69,59 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler { private NioEventLoopGroup serverWorkerGroup; @Autowired private ProxyConfig proxyConfig; + @Autowired + private LicenseService licenseService; + @Autowired + private UserService userService; + @Autowired + private PortMappingService portMappingService; @Override public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) { - ProxyClientConfig clientConfig = JSONObject.parseObject(proxyMessage.getInfo(), ProxyClientConfig.class); - String clientKey = clientConfig.getClientKey(); - if (!proxyConfig.getLicenseMap().containsKey(clientKey)) { - ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "无效的clientKey")); + String licenseKey = proxyMessage.getInfo(); + if (StringUtil.isEmpty(licenseKey)) { + ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "license不能为空!")); + ctx.channel().close(); + return; + } + LicenseDO licenseDO = licenseService.findByKey(licenseKey); + if (null == licenseDO) { + ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "license不存在!")); + ctx.channel().close(); + return; + } + if (EnableStatusEnum.DISABLE.getStatus().equals(licenseDO.getEnable())) { + ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "当前license已被禁用!")); + ctx.channel().close(); + return; + } + UserDO userDO = userService.findById(licenseDO.getId()); + if (null == userDO || EnableStatusEnum.DISABLE.getStatus().equals(userDO.getEnable())) { + ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "当前license无效!")); + ctx.channel().close(); + return; + } + List portMappingList = portMappingService.findEnableListByLicenseId(licenseDO.getId()); + if (CollectionUtil.isEmpty(portMappingList)) { + ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "当前license没有可用的端口映射!")); ctx.channel().close(); return; } - if (proxyConfig.getLicenseMap().get(clientKey) != -1 && clientConfig.getProxy().size() > proxyConfig.getLicenseMap().get(clientKey)) { - ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "代理端口数超过license限制")); - ctx.channel().close(); - return; - } - - ProxyServerConfig.getInstance().addClientConfig(clientConfig); - List ports = ProxyServerConfig.getInstance().getClientInetPorts(clientKey); + ProxyServerConfig.getInstance().addClientConfig(licenseKey, portMappingList); + List ports = ProxyServerConfig.getInstance().getClientInetPorts(licenseKey); if (ports == null) { ctx.channel().close(); return; } - Channel channel = ProxyChannelManager.getCmdChannel(clientKey); + Channel channel = ProxyChannelManager.getCmdChannel(licenseKey); if (channel != null) { ctx.channel().close(); return; } - ProxyChannelManager.addCmdChannel(ports, clientKey, ctx.channel()); + ProxyChannelManager.addCmdChannel(ports, licenseKey, ctx.channel()); startUserPortServer(ports); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java index a1746937..7ef01b6c 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java @@ -182,6 +182,10 @@ public class LicenseService { licenseMapper.reset(id, key, now); } + public LicenseDO findByKey(String license) { + return licenseMapper.findByKey(license); + } + /** * 脱敏处理 * 非当前登录人的license,一律脱敏 diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/PortMappingService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/PortMappingService.java index 37b67b02..611a5101 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/PortMappingService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/PortMappingService.java @@ -203,4 +203,13 @@ public class PortMappingService { portMappingMapper.delete(id); } + /** + * 根据license查询可用的端口映射列表 + * @param licenseId + * @return + */ + public List findEnableListByLicenseId(Integer licenseId) { + return portMappingMapper.findEnableListByLicenseId(licenseId); + } + } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java index b5051d1c..4b8f5cdd 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java @@ -119,6 +119,10 @@ public class UserService { return userMapper.findById(userTokenDO.getUserId()); } + public UserDO findById(Integer id) { + return userMapper.findById(id); + } + public void updateTokenExpirationTime(String token) { Date now = new Date(); Date expirationTime = DateUtil.addDate(now, Calendar.HOUR, 1); diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/util/ProxyChannelManager.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/util/ProxyChannelManager.java index 3b980b31..00400401 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/util/ProxyChannelManager.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/util/ProxyChannelManager.java @@ -73,7 +73,7 @@ public class ProxyChannelManager { channel.attr(CHANNEL_PORT).set(ports); channel.attr(CHANNEL_CLIENT_KEY).set(clientKey); - channel.attr(USER_CHANNELS).set(new ConcurrentHashMap()); + channel.attr(USER_CHANNELS).set(new ConcurrentHashMap<>()); cmdChannels.put(clientKey, channel); }