From bd4af9261d6c1934100a0c1e379a34bc5eb313c2 Mon Sep 17 00:00:00 2001 From: zeaslity Date: Wed, 1 Mar 2023 17:41:37 +0800 Subject: [PATCH] =?UTF-8?q?[server][=20xray]-=20=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E9=93=BE=E9=85=8D=E7=BD=AE=E7=94=9F=E6=88=90?= =?UTF-8?q?=20-=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xray/service/XrayConfigPersistor.java | 15 +- .../xray/service/XrayCoreServiceImpl.java | 142 ++++++++++-------- 2 files changed, 94 insertions(+), 63 deletions(-) diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java b/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java index 692b7da..09cf2f4 100644 --- a/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java +++ b/server/src/main/java/io/wdd/func/xray/service/XrayConfigPersistor.java @@ -14,6 +14,7 @@ import io.wdd.func.xray.beans.node.XrayConfigInfo; import io.wdd.func.xray.beans.xray.XrayConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; @@ -49,12 +50,21 @@ public class XrayConfigPersistor { /** * 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中 * + * @param isOutBoundFree * @param xrayConfig * @param currentVersion * @param proxyNode * @return */ public XrayConfigInfo persist(XrayConfig xrayConfig, int currentVersion, ProxyNode proxyNode) { + + // 从缓存层获取信息 + XrayConfigInfo xrayConfigInfo = proxyNode.getXrayConfigInfo(); + if (ObjectUtils.isEmpty(xrayConfigInfo)) { + xrayConfigInfo = new XrayConfigInfo(); + proxyNode.setXrayConfigInfo(xrayConfigInfo); + } + try { // 将生成的xrayConfig直接写为字符串 String resultContent = objectWriter @@ -74,10 +84,11 @@ public class XrayConfigPersistor { currentVersion ); - // 文件写入完成,保存文件信息 - XrayConfigInfo xrayConfigInfo = new XrayConfigInfo(); xrayConfigInfo.setXrayConfigFile(xrayConfigFile); xrayConfigInfo.setXrayConfigFileName(fileName); + + + // 文件写入完成,保存文件信息 xrayConfigInfo.setXrayConfig(xrayConfig); return xrayConfigInfo; diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java b/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java index 94884a2..3e58be0 100644 --- a/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java +++ b/server/src/main/java/io/wdd/func/xray/service/XrayCoreServiceImpl.java @@ -10,11 +10,14 @@ import io.wdd.func.xray.beans.xray.protocol.inbound.vmess.InboundConfigurationOb import io.wdd.func.xray.beans.xray.protocol.inbound.vmess.VMESS; import io.wdd.func.xray.beans.xray.protocol.outbound.Freedom; import io.wdd.func.xray.beans.xray.protocol.outbound.OutboundConfigurationObject; +import io.wdd.func.xray.beans.xray.transport.InboundObject; import io.wdd.func.xray.beans.xray.transport.OutboundObject; import io.wdd.func.xray.persisit.XrayDBOperator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.lang.reflect.InvocationTargetException; @@ -33,14 +36,12 @@ import static io.wdd.func.xray.service.XrayConfigPersistor.cleanVersion; @Slf4j public class XrayCoreServiceImpl implements XrayCoreService { + private static final String ProxyChainSplitor = "->"; @Resource XrayConfigPersistor xrayConfigPersistor; - @Resource XrayDBOperator xrayDBOperator; - private static final String ProxyChainSplitor = "->"; - @Override public List> transformProxyChainString(List proxyChainList, boolean isTopicName) { @@ -90,17 +91,21 @@ public class XrayCoreServiceImpl implements XrayCoreService { // value => Xray Config Json // HashMap resultMap = new HashMap<>(); + // 清除tmp目录时候使用的一个锁 + + int currentVersion = cleanVersion.get(); allNetworkPathList .stream() .forEach( networkPathList -> { - // 每一条每一条的执行,依次添加相应的 in-out 连接 generateXrayJsonSinglePath( - networkPathList + networkPathList, + currentVersion ); } ); + // 拿到所有的proxyNode Set proxyNodeSet = allNetworkPathList .stream() @@ -127,7 +132,8 @@ public class XrayCoreServiceImpl implements XrayCoreService { return PROXY_NODE_TOPIC_NAME_MAP; } - private void generateXrayJsonSinglePath(List networkPathList) { + private void generateXrayJsonSinglePath(List networkPathList, int currentVersion) { + int pathLength = networkPathList.size(); // 采用 VMESS + websocket的形式形成 链状代理 @@ -138,7 +144,6 @@ public class XrayCoreServiceImpl implements XrayCoreService { String uuid = UUID .randomUUID() .toString(); - ClientObject clientObject = ClientObject .builder() .id(uuid) @@ -150,19 +155,14 @@ public class XrayCoreServiceImpl implements XrayCoreService { int port = 19999; - // 清楚tmp目录时候使用的一个锁 - int currentVersion = cleanVersion.get(); + for (int pos = 0; pos < pathLength; pos++) { ProxyNode proxyNode = networkPathList.get(pos); - // 最后一个节点需要进行 FreeOutbound的构造 - boolean isOutBoundFree = pos == pathLength - 1; - // 构造 xrayConfig XrayConfig xrayConfig = doBuildXrayConfig( - isOutBoundFree, tag, clientObject, port, @@ -170,22 +170,29 @@ public class XrayCoreServiceImpl implements XrayCoreService { pos ); - // 持久化 Xray生成的文件信息 + // 在 缓存层 持久化 Xray生成的文件信息 XrayConfigInfo xrayConfigInfo = xrayConfigPersistor.persist( xrayConfig, currentVersion, proxyNode ); - proxyNode.setXrayConfigInfo(xrayConfigInfo); } } - private XrayConfig doBuildXrayConfig(boolean isOutBoundFree, String tag, ClientObject clientObject, int port, List networkPathList, int pos) { + private XrayConfig doBuildXrayConfig(String tag, ClientObject clientObject, int port, List networkPathList, int pos) { - XrayConfig xrayConfig = new XrayConfig(); + // 需要从现有的XrayConfig基础上进行生成 + // 尝试从 缓存层获取 + XrayConfig xrayConfig = networkPathList + .get(pos) + .getXrayConfigInfo() + .getXrayConfig(); + if (ObjectUtils.isEmpty(xrayConfig)) { + xrayConfig = new XrayConfig(); + } // 设置Log属性 xrayConfig.setLog(LogTemplate); @@ -198,26 +205,16 @@ public class XrayCoreServiceImpl implements XrayCoreService { tag ); - if (isOutBoundFree) { - // 最后一个直接出去就行了 - // 设置FreeOut - buildOutboundFree( - xrayConfig, - tag - ); - } else { - // 中间节点,需要有特定的输出 - // 设置 outbounds的信息 - buildOutbound( - xrayConfig, - networkPathList, - pos, - clientObject, - tag, - port - ); - } - + // 中间节点,需要有特定的输出 + // 设置 outbounds的信息 + buildOutbound( + xrayConfig, + networkPathList, + pos, + clientObject, + tag, + port + ); // 设置 路由信息 buildRouting( @@ -241,8 +238,13 @@ public class XrayCoreServiceImpl implements XrayCoreService { private void buildRouting(XrayConfig xrayConfig, String tag) { - RoutingObject routingObject = new RoutingObject(); - routingObject.setDomainStrategy("IPIfNonMatch"); + // 从缓存中获取 + RoutingObject routingObject = xrayConfig.getRouting(); + if (ObjectUtils.isEmpty(routingObject)) { + routingObject = new RoutingObject(); + routingObject.setDomainStrategy("IPIfNonMatch"); + xrayConfig.setRouting(routingObject); + } RuleObject ruleObject = RuleObject .builder() @@ -251,16 +253,39 @@ public class XrayCoreServiceImpl implements XrayCoreService { .outboundTag(tag) .build(); - routingObject.setRules( - new ArrayList<>( - List.of(ruleObject) - ) - ); + List ruleObjectList = routingObject.getRules(); + if (CollectionUtils.isEmpty(ruleObjectList)) { + ruleObjectList = new ArrayList<>(); + routingObject.setRules(ruleObjectList); + } - xrayConfig.setRouting(routingObject); + ruleObjectList.add(ruleObject); } private void buildOutbound(XrayConfig xrayConfig, List networkPathList, int pos, ClientObject clientObject, String tag, Integer port) { + + // 从缓存中获取 + List outboundObjectList = xrayConfig.getOutbounds(); + if (CollectionUtils.isEmpty(outboundObjectList)) { + outboundObjectList = new ArrayList<>(); + xrayConfig.setOutbounds(outboundObjectList); + } + + int ChainLastPosIndex = networkPathList.size() - 1; + + if (pos == ChainLastPosIndex) { + // 代理链的最后一位 + if (!outboundObjectList.contains(OutboundFree)) { + outboundObjectList.add(OutboundFree); + } + if (!outboundObjectList.contains(OutboundBlackHole)) { + outboundObjectList.add(OutboundBlackHole); + } + return; + } + + // 中间节点,需要进行特定的构建 + io.wdd.func.xray.beans.xray.protocol.outbound.VMESS vmessOutbound = new io.wdd.func.xray.beans.xray.protocol.outbound.VMESS(); try { BeanUtils.copyProperties( @@ -294,18 +319,18 @@ public class XrayCoreServiceImpl implements XrayCoreService { List.of(clientObject) ); - xrayConfig.setOutbounds( - new ArrayList<>( - List.of( - vmessOutbound, - OutboundFree, - OutboundBlackHole - ) - ) - ); + outboundObjectList.add(vmessOutbound); } private void buildInbound(XrayConfig xrayConfig, ClientObject clientObject, Integer port, String tag) { + + // 从缓存中获取 + List inboundObjectList = xrayConfig.getInbounds(); + if (CollectionUtils.isEmpty(inboundObjectList)) { + inboundObjectList = new ArrayList<>(); + xrayConfig.setInbounds(inboundObjectList); + } + VMESS inboundObject = new VMESS(); try { @@ -332,13 +357,8 @@ public class XrayCoreServiceImpl implements XrayCoreService { inboundObject.setSettings(inboundConfigurationObject); - xrayConfig.setInbounds( - new ArrayList<>( - List.of( - inboundObject - ) - ) - ); + // 增加进去 + inboundObjectList.add(inboundObject); } /**