diff --git a/.run/RunServerToRemote.run.xml b/.run/RunServerToRemote.run.xml index 62af215..7b815ec 100644 --- a/.run/RunServerToRemote.run.xml +++ b/.run/RunServerToRemote.run.xml @@ -14,6 +14,14 @@ diff --git a/common/src/main/java/io/wdd/common/utils/TimeUtils.java b/common/src/main/java/io/wdd/common/utils/TimeUtils.java index 38d5e53..11d1e54 100644 --- a/common/src/main/java/io/wdd/common/utils/TimeUtils.java +++ b/common/src/main/java/io/wdd/common/utils/TimeUtils.java @@ -1,5 +1,7 @@ package io.wdd.common.utils; +import org.apache.commons.lang3.ObjectUtils; + import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; @@ -24,6 +26,15 @@ public class TimeUtils { private static final Map times = new LinkedHashMap<>(); + private static final String FULL_SPLIT_TIME_FORMAT = "yyyy-MM-dd-HH-mm-ss"; + private static final String COMMON_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + + /** + * 在五秒误差内的一个统一时间 + */ + private static LocalDateTime UNIFORM_TIME; + static { times.put( "year", @@ -59,7 +70,7 @@ public class TimeUtils { byte[] timeBytes = LocalDateTime .now(SYSTEM_TIME_ZONE_ID) - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + .format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT)) .getBytes(StandardCharsets.UTF_8); return ByteBuffer.wrap(timeBytes); @@ -70,12 +81,34 @@ public class TimeUtils { return LocalDateTime.now(SYSTEM_TIME_ZONE_ID); } + + /** + * @return 获取五秒时间误差内的统一时间 + */ + public static String UniformFormatTimeString() { + + if (ObjectUtils.isEmpty(UNIFORM_TIME)) { + UNIFORM_TIME = currentTime(); + return currentFormatTimeString(); + } + + // 旧的时间和新时间之家误差小于5秒,那么使用同一个时间 + if (UNIFORM_TIME + .plusSeconds(5) + .isAfter(currentTime())) { + UNIFORM_TIME = currentTime(); + } + + return localDateTimeFormatString(UNIFORM_TIME); + + } + /** * @return 格式化 去掉时间中的毫秒数 */ public static LocalDateTime currentFormatTime() { - DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT); String format = LocalDateTime .now(SYSTEM_TIME_ZONE_ID) @@ -92,7 +125,7 @@ public class TimeUtils { public static String currentFormatTimeString() { return currentFormatTime() - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss")); + .format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT)); } public static LocalDateTime cvFromDate(Date date) { @@ -113,7 +146,7 @@ public class TimeUtils { return LocalDateTime .now(SYSTEM_TIME_ZONE_ID) - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + .format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT)); } /** @@ -123,13 +156,29 @@ public class TimeUtils { return LocalDateTime .now(SYSTEM_TIME_ZONE_ID) - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss")); + .format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT)); } + /** + * 输出格式为 COMMON_TIME_FORMAT "yyyy-MM-dd HH:mm:ss" + * + * @param time + * @return + */ public static String localDateTimeString(LocalDateTime time) { - return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + return time.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT)); + } + + /** + * 输出格式为 FULL_SPLIT_TIME_FORMAT "yyyy-MM-dd-HH-mm-ss" + * + * @param time + * @return + */ + public static String localDateTimeFormatString(LocalDateTime time) { + return time.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT)); } public static String toRelative(long duration, int maxLevel) { diff --git a/server/src/main/java/io/wdd/func/controller/XrayController.java b/server/src/main/java/io/wdd/func/controller/XrayController.java index e688fc1..b4b11e5 100644 --- a/server/src/main/java/io/wdd/func/controller/XrayController.java +++ b/server/src/main/java/io/wdd/func/controller/XrayController.java @@ -7,14 +7,15 @@ import io.swagger.annotations.ApiParam; import io.wdd.common.beans.response.R; import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.XrayConfigInfo; -import io.wdd.func.xray.service.XrayConfigDistribute; +import io.wdd.func.xray.service.XrayCallAgent; import io.wdd.func.xray.service.XrayCoreService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.*; +import java.util.HashMap; +import java.util.List; -import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_TOPIC_NAME_MAP; @RestController @RequestMapping("/server/func/xray") @@ -25,7 +26,7 @@ public class XrayController { XrayCoreService xrayCoreService; @Resource - XrayConfigDistribute xrayConfigDistribute; + XrayCallAgent xrayCallAgent; @PostMapping("/chain/transform") @@ -47,7 +48,7 @@ public class XrayController { } @PostMapping("/chain/debug") - @ApiOperation("[解析] - 代理链完整配置") + @ApiOperation("[解析] - debug 代理链完整配置") public R> debugProxyChainString( @ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔") @RequestParam("proxyChainList") List proxyChainList, @@ -65,6 +66,23 @@ public class XrayController { ); } + @PostMapping("/chain/procedure") + @ApiOperation("[实际] - 代理链全流程配置上传下发") + public R> ProxyChainUpdateProcedure( + @ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔") + @RequestParam("proxyChainList") List proxyChainList, + @ApiParam(name = "isTopicName", value = "是否使用AgentTopicName, 默认为AgentName") + @RequestParam(value = "isTopicName", required = false, defaultValue = "false") boolean isTopicName + ) { + + return R.ok( + xrayCoreService.ProxyChainUpdateProcedure( + proxyChainList, + isTopicName + ) + ); + } + @PostMapping("/cache/manual") @ApiOperation("[缓存] - 手动更新代理链缓存") public R> manualUpdateProxyNodeListCache() { @@ -83,7 +101,7 @@ public class XrayController { } - @GetMapping("/test") + /*@GetMapping("/test") public void test() { List> allNetworkPathList = new ArrayList<>(); @@ -132,11 +150,11 @@ public class XrayController { xrayCoreService.generateXrayConfigFromNodeList(allNetworkPathList); - xrayConfigDistribute.uploadXrayConfigToOSS(allNetworkPathList.get(0)); + xrayCallAgent.uploadXrayConfigToOSS(allNetworkPathList.get(0)); - xrayConfigDistribute.buildXrayUpdateResult(allNetworkPathList.get(0)); + xrayCallAgent.buildXrayUpdateResult(allNetworkPathList.get(0)); System.out.println("Xray controller test() 结束!"); - } + }*/ } diff --git a/server/src/main/java/io/wdd/func/oss/config/OSSConfiguration.java b/server/src/main/java/io/wdd/func/oss/config/OSSConfiguration.java index 64e3055..dd10bc4 100644 --- a/server/src/main/java/io/wdd/func/oss/config/OSSConfiguration.java +++ b/server/src/main/java/io/wdd/func/oss/config/OSSConfiguration.java @@ -33,7 +33,6 @@ public class OSSConfiguration { */ public static final List ALL_OSS_CONFIG = new ArrayList<>(); - /** * 初始数据 */ diff --git a/server/src/main/java/io/wdd/func/oss/service/OssBackendSelect.java b/server/src/main/java/io/wdd/func/oss/service/OssBackendSelect.java index c978af1..149ab23 100644 --- a/server/src/main/java/io/wdd/func/oss/service/OssBackendSelect.java +++ b/server/src/main/java/io/wdd/func/oss/service/OssBackendSelect.java @@ -1,6 +1,5 @@ package io.wdd.func.oss.service; -import com.amazonaws.services.s3.AmazonS3; import io.wdd.func.oss.config.OssConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -14,13 +13,18 @@ import static io.wdd.func.oss.config.OSSConfiguration.ALL_OSS_CONFIG; /** * 对象存储后端选择 - * 指定一系列的策略,选出最为合适的OSS存储后端位置 + * 指定一系列的策略,选出最为合适的OSS存储后端位置 */ @Service @Slf4j public class OssBackendSelect { - public OssConfig one(String BackendPrefixName){ + /** + * 根据 OSS桶的名称前缀 返回一个桶 + * @param BackendPrefixName OSS桶的名称前缀 + * @return + */ + public OssConfig one(String BackendPrefixName) { if (StringUtils.isEmpty(BackendPrefixName)) { return oneRandom(); @@ -41,8 +45,10 @@ public class OssBackendSelect { // 随机选择一个, 也算是一个算法吧 Random random = new Random(); int pos = random - .ints(0, - ossConfigList.size()) + .ints( + 0, + ossConfigList.size() + ) .findFirst() .getAsInt(); @@ -50,20 +56,31 @@ public class OssBackendSelect { return ossConfigList.get(pos); } + /** + * @return 返回 随意一个桶 + */ public OssConfig oneRandom() { Random random = new Random(); int pos = random - .ints(0, - ALL_OSS_CONFIG.size()) + .ints( + 0, + ALL_OSS_CONFIG.size() + ) .findFirst() .getAsInt(); return ALL_OSS_CONFIG.get(pos); } - public List all(String BackendPrefixName){ + /** + * 根据 OSS桶的名称前缀 返回所有的桶 + * + * @param BackendPrefixName OSS桶的名称前缀 + * @return + */ + public List all(String BackendPrefixName) { return ALL_OSS_CONFIG .stream() diff --git a/server/src/main/java/io/wdd/func/xray/beans/config/TcpHttpHeaderTemplate.java b/server/src/main/java/io/wdd/func/xray/beans/config/TcpHttpHeaderTemplate.java index c772331..63a229a 100644 --- a/server/src/main/java/io/wdd/func/xray/beans/config/TcpHttpHeaderTemplate.java +++ b/server/src/main/java/io/wdd/func/xray/beans/config/TcpHttpHeaderTemplate.java @@ -35,7 +35,7 @@ public class TcpHttpHeaderTemplate { "/news/", "/finance/", "/sports/", - "weathers" + "/weathers" ); diff --git a/server/src/main/java/io/wdd/func/xray/beans/xray/share/VmessShare.java b/server/src/main/java/io/wdd/func/xray/beans/xray/share/VmessShare.java new file mode 100644 index 0000000..ff89ed3 --- /dev/null +++ b/server/src/main/java/io/wdd/func/xray/beans/xray/share/VmessShare.java @@ -0,0 +1,43 @@ +package io.wdd.func.xray.beans.xray.share; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@NoArgsConstructor +@Data +@AllArgsConstructor +@SuperBuilder(toBuilder = true) +public class VmessShare { + + @JsonProperty("v") + private String v; + @JsonProperty("ps") + private String ps; + @JsonProperty("add") + private String add; + @JsonProperty("port") + private String port; + @JsonProperty("id") + private String id; + @JsonProperty("aid") + private String aid; + @JsonProperty("scy") + private String scy; + @JsonProperty("net") + private String net; + @JsonProperty("type") + private String type; + @JsonProperty("host") + private String host; + @JsonProperty("path") + private String path; + @JsonProperty("tls") + private String tls; + @JsonProperty("sni") + private String sni; + @JsonProperty("alpn") + private String alpn; +} diff --git a/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java b/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java index 785f5d8..25d1d54 100644 --- a/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java +++ b/server/src/main/java/io/wdd/func/xray/persisit/XrayDBOperator.java @@ -4,7 +4,6 @@ import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.ProxyNodeType; import io.wdd.func.xray.beans.node.XrayConfigInfo; import io.wdd.server.beans.vo.ServerInfoVO; -import io.wdd.server.coreService.CoreAppService; import io.wdd.server.coreService.CoreServerService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -29,8 +28,6 @@ public class XrayDBOperator { @Resource CoreServerService coreServerService; - @Resource - CoreAppService coreAppService; @PostConstruct public void cache() { @@ -50,7 +47,6 @@ public class XrayDBOperator { transferServerInfoToProxyNode(serverInfoVOList); - } private void transferServerInfoToProxyNode(List serverInfoVOList) { @@ -141,6 +137,16 @@ public class XrayDBOperator { } ); + // 缓存订阅虚拟节点 + ProxyNode subscribeProxyNode = buildSubscribeProxyNode(); + PROXY_NODE_MAP.put( + subscribeProxyNode.getName(), + subscribeProxyNode + ); + PROXY_NODE_TOPIC_NAME_MAP.put( + subscribeProxyNode.getName(), + subscribeProxyNode + ); //help gc bitmap = null; @@ -148,6 +154,17 @@ public class XrayDBOperator { } + private ProxyNode buildSubscribeProxyNode() { + + return ProxyNode + .builder() + .name(SUBSCRIBE_NODE_NAME) + .num(0) + .agentName("subscribe-virtual-node") + .xrayConfigInfo(new XrayConfigInfo()) + .build(); + } + private ProxyNodeType convertNodeType(Integer proxyType) { if (null == proxyType) { diff --git a/server/src/main/java/io/wdd/func/xray/persisit/XrayOssOperator.java b/server/src/main/java/io/wdd/func/xray/persisit/XrayOssOperator.java new file mode 100644 index 0000000..021dbe0 --- /dev/null +++ b/server/src/main/java/io/wdd/func/xray/persisit/XrayOssOperator.java @@ -0,0 +1,115 @@ +package io.wdd.func.xray.persisit; + +import io.wdd.common.handler.MyRuntimeException; +import io.wdd.func.oss.config.OctopusObjectSummary; +import io.wdd.func.oss.config.OssConfig; +import io.wdd.func.oss.service.OSSCoreService; +import io.wdd.func.oss.service.OssBackendSelect; +import io.wdd.func.xray.beans.node.ProxyNode; +import io.wdd.func.xray.beans.node.XrayConfigInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; + +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_MAP; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.SUBSCRIBE_NODE_NAME; + +@Service +@Slf4j +public class XrayOssOperator { + + /** + * 订阅文件实际存储的桶的名称 + * 实际为 Oracle-Seoul-2 下面的桶 + */ + private static final String SUBSCRIBE_OSS_BUCKET_PREFIX = "seoul"; + @Resource + OssBackendSelect ossBackendSelect; + @Resource + OSSCoreService ossCoreService; + + /** + * 为代理链的每一个节点 上传配置文件到OSS中 + * + * @param allProxyNodeList + */ + public void uploadXrayConfigToOSS(Collection allProxyNodeList) { + + // 所有的文件全部存储至一个对象存储的后端中 + OssConfig ossConfig = ossBackendSelect.oneRandom(); + log.info( + "[Xray] 开始上传所有的xray config 至对象存储中 => [{}]", + ossConfig.getName() + "-" + ossConfig.getRegion() + ); + + // 依次存储所有的config文件 + allProxyNodeList + .stream() + .forEach( + node -> { + XrayConfigInfo xrayConfigInfo = node.getXrayConfigInfo(); + // 上传OSS + OctopusObjectSummary octopusObjectSummary = ossCoreService + .createObject( + ossConfig, + xrayConfigInfo.getXrayConfigFileName(), + xrayConfigInfo.getXrayConfigFile() + ); + // 设置oss的相关信息 + + xrayConfigInfo.setObjectSummary(octopusObjectSummary); + } + ); + } + + /** + * 上传 订阅文件信息 件到OSS + * + * @return + */ + public XrayConfigInfo uploadSubscribeFileToOSS() { + + XrayConfigInfo subscribeXrayConfigInfo = PROXY_NODE_MAP + .get(SUBSCRIBE_NODE_NAME). + getXrayConfigInfo(); + + + // 存储到特定的桶中 + OssConfig ossConfig = ossBackendSelect.one(SUBSCRIBE_OSS_BUCKET_PREFIX); + + log.debug( + "开始存储 Xray订阅文件 [ {} ] 至OSS [ {} ]中", + subscribeXrayConfigInfo, + ossConfig + ); + + // 删除旧的订阅信息 + boolean deleteObject = ossCoreService.deleteObject( + ossConfig, + SUBSCRIBE_OSS_BUCKET_PREFIX, + subscribeXrayConfigInfo.getXrayConfigFileName() + ); + if (!deleteObject) { + log.error( + "删除旧的订阅信息失败! 请检查桶 => [{}]", + ossConfig + ); + throw new MyRuntimeException(); + } + + // 上传新的订阅信息 + OctopusObjectSummary objectSummary = ossCoreService.createObject( + ossConfig, + SUBSCRIBE_OSS_BUCKET_PREFIX, + subscribeXrayConfigInfo.getXrayConfigFile() + ); + + subscribeXrayConfigInfo.setObjectSummary(objectSummary); + + return subscribeXrayConfigInfo; + } + + +} diff --git a/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java b/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java index af846f4..35f8bfb 100644 --- a/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java +++ b/server/src/main/java/io/wdd/func/xray/persisit/cache/EdgeWeightCache.java @@ -1,84 +1,80 @@ package io.wdd.func.xray.persisit.cache; -import io.wdd.func.xray.beans.node.Edge; - -import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*; - -public class EdgeWeightCache { - - - public static Edge chengduToShanghai; - - public static Edge shanghaiToSeoul2; - public static Edge shanghaiToTokyo2; - - public static Edge hongkongToSeoul2; - public static Edge hongkongToTokyo2; - public static Edge hongkongToPhoenix2; - - public static Edge seoul2ToTokyo2; - public static Edge seoul2ToPhoenix2; - public static Edge seoul2ToLondon2; - - public static Edge tokyo2ToPhoenix2; - public static Edge tokyo2ToLondon2; - - /** - * 计算 网络路径中的路径权重 - * 值的范围在0-100,数字越小表示阻力越小 - * 指标 1.延迟 2.丢包率 3.带宽 4.节点稳定性 - */ - public void EdgeWeightCalculate(){ - - - - } - - static { - - chengduToShanghai = new Edge( - chengdu, - shanghai, - 10 - ); - - shanghaiToSeoul2 = new Edge( - shanghai, - seoul2, - 40 - ); - - shanghaiToTokyo2 = new Edge( - shanghai, - tokyo2, - 60 - ); - - seoul2ToTokyo2 = new Edge( - seoul2, - tokyo2, - 10 - ); - tokyo2ToPhoenix2 = new Edge( - tokyo2, - phoenix2, - 30 - ); - tokyo2ToLondon2 = new Edge( - tokyo2, - london2, - 50 - ); - hongkongToTokyo2 = new Edge( - hongkong, - tokyo2, - 40 - ); - hongkongToSeoul2 = new Edge( - hongkong, - seoul2, - 20 - ); - - } -} +//public class EdgeWeightCache { +// +// +// public static Edge chengduToShanghai; +// +// public static Edge shanghaiToSeoul2; +// public static Edge shanghaiToTokyo2; +// +// public static Edge hongkongToSeoul2; +// public static Edge hongkongToTokyo2; +// public static Edge hongkongToPhoenix2; +// +// public static Edge seoul2ToTokyo2; +// public static Edge seoul2ToPhoenix2; +// public static Edge seoul2ToLondon2; +// +// public static Edge tokyo2ToPhoenix2; +// public static Edge tokyo2ToLondon2; +// +// /** +// * 计算 网络路径中的路径权重 +// * 值的范围在0-100,数字越小表示阻力越小 +// * 指标 1.延迟 2.丢包率 3.带宽 4.节点稳定性 +// */ +// public void EdgeWeightCalculate(){ +// +// +// +// } +// +// static { +// +// chengduToShanghai = new Edge( +// chengdu, +// shanghai, +// 10 +// ); +// +// shanghaiToSeoul2 = new Edge( +// shanghai, +// seoul2, +// 40 +// ); +// +// shanghaiToTokyo2 = new Edge( +// shanghai, +// tokyo2, +// 60 +// ); +// +// seoul2ToTokyo2 = new Edge( +// seoul2, +// tokyo2, +// 10 +// ); +// tokyo2ToPhoenix2 = new Edge( +// tokyo2, +// phoenix2, +// 30 +// ); +// tokyo2ToLondon2 = new Edge( +// tokyo2, +// london2, +// 50 +// ); +// hongkongToTokyo2 = new Edge( +// hongkong, +// tokyo2, +// 40 +// ); +// hongkongToSeoul2 = new Edge( +// hongkong, +// seoul2, +// 20 +// ); +// +// } +//} diff --git a/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java b/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java index b9aa04b..a933364 100644 --- a/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java +++ b/server/src/main/java/io/wdd/func/xray/persisit/cache/ProxyNodeCache.java @@ -1,7 +1,6 @@ package io.wdd.func.xray.persisit.cache; import io.wdd.func.xray.beans.node.ProxyNode; -import io.wdd.func.xray.beans.node.ProxyNodeType; import java.util.HashMap; @@ -20,21 +19,26 @@ public class ProxyNodeCache { public static final HashMap PROXY_NODE_INDEX_MAP = new HashMap<>(); - public static ProxyNode chengdu; - public static ProxyNode shanghai; - public static ProxyNode hongkong; - public static ProxyNode seoul2; - public static ProxyNode tokyo2; - public static ProxyNode phoenix2; - public static ProxyNode london2; + /** + * 订阅信息的虚拟节点,用于存储订阅内容的信息 + */ + public static final String SUBSCRIBE_NODE_NAME = "SUBSCRIBE"; - // 开发使用 - public static ProxyNode chengduAgent; - public static ProxyNode tokyoDev; - public static ProxyNode seoul5; + private static ProxyNode chengdu; + private static ProxyNode shanghai; + private static ProxyNode hongkong; + private static ProxyNode seoul2; + private static ProxyNode tokyo2; + private static ProxyNode phoenix2; + private static ProxyNode london2; - static { + private static ProxyNode chengduAgent; + private static ProxyNode tokyoDev; + private static ProxyNode seoul5; + + + /*static { chengdu = ProxyNode .builder() @@ -185,6 +189,6 @@ public class ProxyNodeCache { seoul5 ); - } + }*/ } diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayConfigDistribute.java b/server/src/main/java/io/wdd/func/xray/service/XrayCallAgent.java similarity index 66% rename from server/src/main/java/io/wdd/func/xray/service/XrayConfigDistribute.java rename to server/src/main/java/io/wdd/func/xray/service/XrayCallAgent.java index 2343bb5..672c22f 100644 --- a/server/src/main/java/io/wdd/func/xray/service/XrayConfigDistribute.java +++ b/server/src/main/java/io/wdd/func/xray/service/XrayCallAgent.java @@ -2,11 +2,7 @@ package io.wdd.func.xray.service; import io.wdd.common.utils.TimeUtils; import io.wdd.func.oss.config.OctopusObjectSummary; -import io.wdd.func.oss.config.OssConfig; -import io.wdd.func.oss.service.OSSCoreService; -import io.wdd.func.oss.service.OssBackendSelect; import io.wdd.func.xray.beans.node.ProxyNode; -import io.wdd.func.xray.beans.node.XrayConfigInfo; import io.wdd.rpc.execute.service.AsyncExecutionService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -14,6 +10,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -27,7 +24,7 @@ import java.util.stream.Collectors; */ @Service @Slf4j -public class XrayConfigDistribute { +public class XrayCallAgent { /** * 存储更新 Xray的命令行 @@ -41,24 +38,6 @@ public class XrayConfigDistribute { static { - /*ArrayList zero = new ArrayList<>( - List.of( - "if", - "[", - "!", - "-f", - "/usr/local/etc/xray/config.json", - "]", - ";", - "then", - "touch", - "/usr/local/etc/xray/config.json", - ";", - "fi" - ) - );*/ - - ArrayList first = new ArrayList<>( List.of( "mv", @@ -70,7 +49,7 @@ public class XrayConfigDistribute { ArrayList second = new ArrayList<>( List.of( "wget", - "url", + "AGENT_SPECIFIC_CONFIG_URL", "-O", "/usr/local/etc/xray/config.json" ) @@ -96,7 +75,6 @@ public class XrayConfigDistribute { ) ); - updateXrayCommandList.add(first); updateXrayCommandList.add(second); updateXrayCommandList.add(third); @@ -104,49 +82,17 @@ public class XrayConfigDistribute { } - - @Resource - OssBackendSelect ossBackendSelect; - @Resource - OSSCoreService ossCoreService; - @Resource AsyncExecutionService executionService; - public void uploadXrayConfigToOSS(List networkPathList) { - - // 所有的文件全部存储至一个对象存储的后端中 - OssConfig ossConfig = ossBackendSelect.oneRandom(); - log.info( - "[Xray] 开始上传所有的xray config 至对象存储中 => [{}]", - ossConfig.getName() + "-" + ossConfig.getRegion() - ); - - // 依次存储所有的config文件 - networkPathList - .stream() - .forEach( - node -> { - XrayConfigInfo xrayConfigInfo = node.getXrayConfigInfo(); - // 上传OSS - OctopusObjectSummary octopusObjectSummary = ossCoreService - .createObject( - ossConfig, - xrayConfigInfo.getXrayConfigFileName(), - xrayConfigInfo.getXrayConfigFile() - ); - // 设置oss的相关信息 - - xrayConfigInfo.setObjectSummary(octopusObjectSummary); - } - ); - } - - public void buildXrayUpdateResult(List networkPathList) { + /** + * 为代理链的每一个节点 构建Xray配置更新命令,然后发送至对应的Agent中 + */ + public void buildXrayUpdateCommandAndCallAgent(Collection allProxyNodeList) { String formatTimeString = TimeUtils.currentFormatTimeString(); - List resultKeyList = networkPathList + List resultKeyList = allProxyNodeList .stream() .map( proxyNode -> { @@ -190,7 +136,9 @@ public class XrayConfigDistribute { updateCommandType, null, updateXrayCommandList, - null + false, + null, + false ); return resultKey; @@ -199,7 +147,7 @@ public class XrayConfigDistribute { .collect(Collectors.toList()); log.info( - "发送所有的配置到各个Agent成功, 结果查看为 => {}", + "为代理链的每一个节点 构建Xray配置更新命令,然后发送至对应的Agent中成功, 结果查看为 => {}", resultKeyList ); 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 3de7fe5..ee9e0de 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 @@ -8,10 +8,10 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import io.wdd.common.handler.MyRuntimeException; -import io.wdd.common.utils.TimeUtils; import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.XrayConfigInfo; import io.wdd.func.xray.beans.xray.XrayConfig; +import io.wdd.func.xray.beans.xray.share.VmessShare; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.ObjectUtils; @@ -22,7 +22,15 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static io.wdd.common.utils.TimeUtils.UniformFormatTimeString; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_MAP; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.SUBSCRIBE_NODE_NAME; /** * 获取rerouces目录 https://blog.csdn.net/pengpengpeng85/article/details/84785575 @@ -34,6 +42,10 @@ import java.util.concurrent.atomic.AtomicInteger; @Service public class XrayConfigPersistor { + /** + * XRAY端口的起始位置 + */ + public static final int XRAY_PORT_MAX = 20000; // 参考 https://github.com/FasterXML/jackson-databind/issues/585 private static final ObjectWriter objectWriter = new ObjectMapper() // 忽略掉 null的字段 @@ -46,10 +58,11 @@ public class XrayConfigPersistor { .withLinefeed("\n") )); private static final String XrayResultPathPrefix = "xrayResult/"; + /** - * XRAY端口的起始位置 + * 存储在对象存储中的订阅文件的名称 */ - public static final int XRAY_PORT_MAX = 20000; + public static final String SUBSCRIBE_FILE_OSS_NAME = "99-subscribe-octopus-latest.txt"; /** * 存储生成的Xray Config的临时文件目录 */ @@ -94,6 +107,7 @@ public class XrayConfigPersistor { } } + /** * 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中 * @@ -117,7 +131,7 @@ public class XrayConfigPersistor { .writeValueAsString(xrayConfig); // 获得到文件名称 - String timeString = TimeUtils.currentFormatTimeString(); + String timeString = UniformFormatTimeString(); String fileName = buildXrayConfigFileName( proxyNode, timeString @@ -144,12 +158,118 @@ public class XrayConfigPersistor { } } + public void subPersist(List vmessShareList) { + + Base64.Encoder encoder = Base64.getEncoder(); + + List subscribeStringList = vmessShareList + .stream() + .map( + vmessShare -> { + + try { + + byte[] vmessShareBytes = objectWriter.writeValueAsBytes(vmessShare); + + return "vmess://" + new String( + encoder.encode(vmessShareBytes), + StandardCharsets.UTF_8 + ); + + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + } + ) + .collect(Collectors.toList()); + + // 实际进行文件的写入 + File subscribeFile = subWrite( + SUBSCRIBE_FILE_OSS_NAME, + subscribeStringList + ); + + // 存储相应的信息 + ProxyNode subscribeNode = PROXY_NODE_MAP.get(SUBSCRIBE_NODE_NAME); + XrayConfigInfo xrayConfigInfo = subscribeNode.getXrayConfigInfo(); + + xrayConfigInfo.setXrayConfigFile(subscribeFile); + xrayConfigInfo.setXrayConfigFileName(SUBSCRIBE_FILE_OSS_NAME); + + } + + private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) { return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json"; } + + /** + * 将订阅信息写入到文件中, 每一行写一个 + * 由于订阅信息的生成一定是晚于代理链的,所以不进行清理工作 + * + * @param fileName + * @return + */ + private File subWrite(String fileName, List subsribeList) { + + // 构造对象开始写入, 生成文件 + File resultFile = getResultFile(fileName); + + FileWriter fileWriter = null; + BufferedWriter bufferedWriter = null; + + try { + log.debug( + "开始写入 Subscribe 进入文件中,文件名为 => {}", + fileName + ); + fileWriter = new FileWriter( + resultFile + ); + bufferedWriter = new BufferedWriter( + fileWriter + ); + + + for (String subsribeString : subsribeList) { + + // 每一行写一个 + bufferedWriter.write(subsribeString); + bufferedWriter.newLine(); + + } + + return resultFile; + + } catch (IOException e) { + log.error( + "打开文件失败,写入tmp文件失败! 文件为 => {}", + resultFile.getName() + ); + throw new MyRuntimeException(e); + } finally { + + try { + // must close + bufferedWriter.close(); + fileWriter.close(); + + } catch (IOException e) { + log.error( + "关闭文件写入流失败!, 请检查 文件为 => [ {} ], 内容为 => {}", + fileName, + subsribeList + ); + throw new MyRuntimeException(e); + } + } + + } + private File write(String fileName, String content, int currentVersion) { log.debug( diff --git a/server/src/main/java/io/wdd/func/xray/service/XrayCoreService.java b/server/src/main/java/io/wdd/func/xray/service/XrayCoreService.java index 4184431..5afcc19 100644 --- a/server/src/main/java/io/wdd/func/xray/service/XrayCoreService.java +++ b/server/src/main/java/io/wdd/func/xray/service/XrayCoreService.java @@ -2,12 +2,14 @@ package io.wdd.func.xray.service; import io.wdd.func.xray.beans.node.ProxyNode; import io.wdd.func.xray.beans.node.XrayConfigInfo; +import io.wdd.func.xray.beans.xray.share.VmessShare; import java.util.HashMap; import java.util.List; public interface XrayCoreService { + /** * 解析代理链字符串,返回完整的代理列表 * @@ -18,6 +20,14 @@ public interface XrayCoreService { List> transformProxyChainString(List proxyChainList, boolean isTopicName); + /** + * 根据代理链生成XrayConfig配置文件和订阅信息文件 + * Config配置会返回, 订阅不会返回 + * Config和Subscribe都会被持久化,并且上传至OSS中,订阅地址为固定的地址 + * + * @param allNetworkPathList 完整的代理链 + * @return + */ List generateXrayConfigFromNodeList(List> allNetworkPathList); @@ -28,4 +38,21 @@ public interface XrayCoreService { */ HashMap manualUpdateProxyNodeListCache(); + + /** + * 根据代理链的配置生成订阅地址 + * + * @param allNetworkPathList + * @param chainPortMap + */ + List generateSubscribeString(List> allNetworkPathList, HashMap chainPortMap); + + /** + * [实际完整流程] - 根据代理链生成XrayConfig配置文件和订阅信息文件 + *

+ * Config配置会返回, 订阅不会返回 + * Config和Subscribe都会被持久化,并且上传至OSS中,订阅地址为固定的地址 + */ + List ProxyChainUpdateProcedure(List proxyChainList, boolean isTopicName); + } 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 6d29651..fcd7ace 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,13 +10,17 @@ 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.share.VmessShare; 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 io.wdd.func.xray.persisit.XrayOssOperator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.ObjectUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; +import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; @@ -28,8 +32,7 @@ import static io.wdd.func.xray.beans.config.InboundVmessHTTPTemplateClass.Inboun import static io.wdd.func.xray.beans.config.InboundVmessHTTPTemplateClass.ListenAddress; import static io.wdd.func.xray.beans.config.LogTemplateClass.LogTemplate; import static io.wdd.func.xray.beans.config.OutboundVmessHTTPTemplateClass.*; -import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_MAP; -import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_TOPIC_NAME_MAP; +import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*; import static io.wdd.func.xray.service.XrayConfigPersistor.*; @Service @@ -42,6 +45,38 @@ public class XrayCoreServiceImpl implements XrayCoreService { @Resource XrayDBOperator xrayDBOperator; + @Resource + XrayCallAgent xrayCallAgent; + + @Resource + XrayOssOperator xrayOssOperator; + + /** + * 根据全部的代理链,获取到 独立的节点Set + * + * @param allNetworkPathList + * @return + */ + @NotNull + private static Set getAllProxyNodeSet(List> allNetworkPathList, boolean includeSubscribeNode) { + // 拿到所有的proxyNode + Set proxyNodeSet = allNetworkPathList + .stream() + .flatMap( + networkPathList -> networkPathList.stream() + ) + .collect(Collectors.toSet()); + // 增加虚拟节点 + if (includeSubscribeNode) { + proxyNodeSet.add( + PROXY_NODE_TOPIC_NAME_MAP.get( + SUBSCRIBE_NODE_NAME + ) + ); + } + return proxyNodeSet; + } + @Override public List> transformProxyChainString(List proxyChainList, boolean isTopicName) { @@ -54,11 +89,19 @@ public class XrayCoreServiceImpl implements XrayCoreService { // 此处获取到的就是 每一个节点的名称 // AgentName 或者 AgentTopicName agentKindOfName -> { + ProxyNode targetNode = null; + if (isTopicName) { - return PROXY_NODE_TOPIC_NAME_MAP.get(agentKindOfName); + targetNode = PROXY_NODE_TOPIC_NAME_MAP.get(agentKindOfName); } else { - return PROXY_NODE_MAP.get(agentKindOfName); + targetNode = PROXY_NODE_MAP.get(agentKindOfName); } + + Assert.notNull( + targetNode, + "输入的代理链字符串有误! 请检查! => " + agentKindOfName + ); + return targetNode; } ) .collect(Collectors.toList()) @@ -92,30 +135,60 @@ public class XrayCoreServiceImpl implements XrayCoreService { // HashMap resultMap = new HashMap<>(); // 清除tmp目录时候使用的一个锁 - int currentVersion = cleanVersion.get(); + + // 记录每条代理链的端口号 + HashMap chainPortMap = new HashMap<>(); + + // 需要事先清空缓存 + manualUpdateProxyNodeListCache(); + + // 生成代理链 allNetworkPathList .stream() .forEach( networkPathList -> { + // 为每一条链生成端口 int chainPort = XRAY_PORT_POOL.decrementAndGet(); + // 为每条链生成相应的tag + // 形式为 Shanghai-amd64-01->Seoul-amd64-04 + String chainTag = generatePathTag(networkPathList); + + // 每条链单独生成Xray Config配置文件 generateXrayJsonSinglePath( chainPort, networkPathList, - currentVersion + currentVersion, + chainTag + ); + + // 为每条代理链 缓存 对应端口 + chainPortMap.put( + chainTag, + chainPort ); } ); + // 生成订阅地址链接 + List vmessShareList = generateSubscribeString( + allNetworkPathList, + chainPortMap + ); - // 拿到所有的proxyNode - Set proxyNodeSet = allNetworkPathList - .stream() - .flatMap( - networkPathList -> networkPathList.stream() - ) - .collect(Collectors.toSet()); + log.debug( + "vmessShareList is => {}", + vmessShareList + ); + + // 开始持久化订阅 + xrayConfigPersistor.subPersist(vmessShareList); + + Set proxyNodeSet = getAllProxyNodeSet( + allNetworkPathList, + true + ); // 返回所有的配置 return proxyNodeSet @@ -139,13 +212,123 @@ public class XrayCoreServiceImpl implements XrayCoreService { return PROXY_NODE_TOPIC_NAME_MAP; } - private void generateXrayJsonSinglePath(int chainPort, List networkPathList, int currentVersion) { + @Override + public List generateSubscribeString(List> allNetworkPathList, HashMap chainPortMap) { + + // 运行到此时,说明配置文件已经生成了, 根据每条链生成订阅定西 + return allNetworkPathList + .stream() + .map( + networkPathList -> { + + // 每条链需要生成相应的唯一标识 + String chainTag = generatePathTag(networkPathList); + + // 拿到每条链的头节点 + ProxyNode headNode = networkPathList.get(0); + + List inboundObjectList = headNode + .getXrayConfigInfo() + .getXrayConfig() + .getInbounds(); + + VMESS realInboundObject = (VMESS) inboundObjectList + .stream() + .filter( + inboundObject -> inboundObject + .getPort() + .equals( + // 拿到每条链的唯一标识 + chainPortMap.get( + chainTag + )) + ) + .findFirst() + .get(); + + return convertInboundToShare( + realInboundObject, + headNode + ); + + } + ) + .collect(Collectors.toList()); + + } + + @Override + public List ProxyChainUpdateProcedure(List proxyChainList, boolean isTopicName) { + + // 解析得到全部的节点 + List> allProxyChainNodeList = this.transformProxyChainString( + proxyChainList, + isTopicName + ); + + // 生成所有的配置 + List xrayConfigInfoList = this.generateXrayConfigFromNodeList(allProxyChainNodeList); + + // 获取到全部的节点 + Set allProxyNodeSet = getAllProxyNodeSet( + allProxyChainNodeList, + false + ); + + // 上传至OSS中 + xrayOssOperator.uploadXrayConfigToOSS(allProxyNodeSet); + xrayOssOperator.uploadSubscribeFileToOSS(); + + // 执行Xray更新操作` + xrayCallAgent.buildXrayUpdateCommandAndCallAgent(allProxyNodeSet); + + + return xrayConfigInfoList; + } + + + /** + * 目前只进行 VMESS协议的转换 + * + * @param realInboundObject + * @param headNode + * @return + */ + private VmessShare convertInboundToShare(VMESS realInboundObject, ProxyNode headNode) { + + // 通常这里只有一个配置 + ClientObject clientObject = realInboundObject + .getSettings() + .getClients() + .get(0); + + + return VmessShare + .builder() + .v("2") + .ps(realInboundObject.getTag()) + .add(headNode.getPublicIPv4()) + .port(String.valueOf(realInboundObject.getPort())) + .id(clientObject.getId()) + .aid(String.valueOf(clientObject.getAlterId())) + .scy("auto") + .net("tcp") + .type("http") + .host("www.baidu.com,www.google.com,www.bing.com,www.github.com") + .path("/news/,/finance/,/sports/,/weathers") + .tls("") + .sni("") + .alpn("") + .build(); + + } + + private void generateXrayJsonSinglePath(int chainPort, List networkPathList, int currentVersion, String chainTag) { int pathLength = networkPathList.size(); // 采用 VMESS + websocket的形式形成 链状代理 // 由于 Vlss+XTLS的形式形成 链状结构 - String tag = generatePathTag(networkPathList); // 通用内容生成 String uuid = UUID @@ -157,7 +340,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { .level(0) // 为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD .alterId(0) - .email(tag + "@octopus.io") + .email(chainTag + "@octopus.io") .build(); for (int pos = 0; pos < pathLength; pos++) { @@ -166,7 +349,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { // 构造 xrayConfig XrayConfig xrayConfig = doBuildXrayConfig( - tag, + chainTag, clientObject, chainPort, networkPathList, @@ -185,7 +368,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { } - private XrayConfig doBuildXrayConfig(String tag, ClientObject clientObject, int chainPort, List networkPathList, int pos) { + private XrayConfig doBuildXrayConfig(String chainTag, ClientObject clientObject, int chainPort, List networkPathList, int pos) { // 需要从现有的XrayConfig基础上进行生成 // 尝试从 缓存层获取 @@ -205,7 +388,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { xrayConfig, clientObject, chainPort, - tag + chainTag ); // 中间节点,需要有特定的输出 @@ -215,23 +398,23 @@ public class XrayCoreServiceImpl implements XrayCoreService { networkPathList, pos, clientObject, - tag, + chainTag, chainPort ); // 设置 路由信息 buildRouting( xrayConfig, - tag + chainTag ); return xrayConfig; } - private void buildOutboundFree(XrayConfig xrayConfig, String tag) { + private void buildOutboundFree(XrayConfig xrayConfig, String chainTag) { OutboundObject freeOut = new Freedom(); - freeOut.setTag(tag); + freeOut.setTag(chainTag); xrayConfig.setOutbounds(new ArrayList<>( List.of(freeOut) @@ -239,7 +422,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { } - private void buildRouting(XrayConfig xrayConfig, String tag) { + private void buildRouting(XrayConfig xrayConfig, String chainTag) { // 从缓存中获取 RoutingObject routingObject = xrayConfig.getRouting(); @@ -252,8 +435,8 @@ public class XrayCoreServiceImpl implements XrayCoreService { RuleObject ruleObject = RuleObject .builder() .type("field") - .inboundTag(List.of(tag)) - .outboundTag(tag) + .inboundTag(List.of(chainTag)) + .outboundTag(chainTag) .build(); List ruleObjectList = routingObject.getRules(); @@ -265,7 +448,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { ruleObjectList.add(ruleObject); } - private void buildOutbound(XrayConfig xrayConfig, List networkPathList, int pos, ClientObject clientObject, String tag, Integer chainPort) { + private void buildOutbound(XrayConfig xrayConfig, List networkPathList, int pos, ClientObject clientObject, String chainTag, Integer chainPort) { // 从缓存中获取 List outboundObjectList = xrayConfig.getOutbounds(); @@ -302,7 +485,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { } // 设置Tag信息 - vmessOutbound.setTag(tag); + vmessOutbound.setTag(chainTag); // 设置出口信息 OutboundConfigurationObject.ServerObject serverObject = vmessOutbound @@ -325,7 +508,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { outboundObjectList.add(vmessOutbound); } - private void buildInbound(XrayConfig xrayConfig, ClientObject clientObject, Integer chainPort, String tag) { + private void buildInbound(XrayConfig xrayConfig, ClientObject clientObject, Integer chainPort, String chainTag) { // 从缓存中获取 List inboundObjectList = xrayConfig.getInbounds(); @@ -345,7 +528,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { throw new RuntimeException(e); } - inboundObject.setTag(tag); + inboundObject.setTag(chainTag); // todo port怎么办 inboundObject.setPort(chainPort); @@ -365,7 +548,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { } /** - * shanghai->seoul2->tokyo2 + * Shanghai-amd64-01->Seoul-amd64-04 * * @param networkPathList 网络路径节点 * @return 路径Tag @@ -377,7 +560,7 @@ public class XrayCoreServiceImpl implements XrayCoreService { .stream() .forEach( networkPath -> { - sb.append(networkPath.getName()); + sb.append(networkPath.getAgentName()); sb.append("->"); } );