[server][xary] - 完成实际Xray配置更新的全流程
This commit is contained in:
@@ -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<List<XrayConfigInfo>> debugProxyChainString(
|
||||
@ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔")
|
||||
@RequestParam("proxyChainList") List<String> proxyChainList,
|
||||
@@ -65,6 +66,23 @@ public class XrayController {
|
||||
);
|
||||
}
|
||||
|
||||
@PostMapping("/chain/procedure")
|
||||
@ApiOperation("[实际] - 代理链全流程配置上传下发")
|
||||
public R<List<XrayConfigInfo>> ProxyChainUpdateProcedure(
|
||||
@ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔")
|
||||
@RequestParam("proxyChainList") List<String> 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<HashMap<String, ProxyNode>> manualUpdateProxyNodeListCache() {
|
||||
@@ -83,7 +101,7 @@ public class XrayController {
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/test")
|
||||
/*@GetMapping("/test")
|
||||
public void test() {
|
||||
|
||||
List<List<ProxyNode>> 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() 结束!");
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ public class OSSConfiguration {
|
||||
*/
|
||||
public static final List<OssConfig> ALL_OSS_CONFIG = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* 初始数据
|
||||
*/
|
||||
|
||||
@@ -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<OssConfig> all(String BackendPrefixName){
|
||||
/**
|
||||
* 根据 OSS桶的名称前缀 返回所有的桶
|
||||
*
|
||||
* @param BackendPrefixName OSS桶的名称前缀
|
||||
* @return
|
||||
*/
|
||||
public List<OssConfig> all(String BackendPrefixName) {
|
||||
|
||||
return ALL_OSS_CONFIG
|
||||
.stream()
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TcpHttpHeaderTemplate {
|
||||
"/news/",
|
||||
"/finance/",
|
||||
"/sports/",
|
||||
"weathers"
|
||||
"/weathers"
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<ServerInfoVO> 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) {
|
||||
|
||||
@@ -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<ProxyNode> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
// );
|
||||
//
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -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<Integer, ProxyNode> 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
|
||||
);
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String> zero = new ArrayList<>(
|
||||
List.of(
|
||||
"if",
|
||||
"[",
|
||||
"!",
|
||||
"-f",
|
||||
"/usr/local/etc/xray/config.json",
|
||||
"]",
|
||||
";",
|
||||
"then",
|
||||
"touch",
|
||||
"/usr/local/etc/xray/config.json",
|
||||
";",
|
||||
"fi"
|
||||
)
|
||||
);*/
|
||||
|
||||
|
||||
ArrayList<String> first = new ArrayList<>(
|
||||
List.of(
|
||||
"mv",
|
||||
@@ -70,7 +49,7 @@ public class XrayConfigDistribute {
|
||||
ArrayList<String> 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<ProxyNode> 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<ProxyNode> networkPathList) {
|
||||
/**
|
||||
* 为代理链的每一个节点 构建Xray配置更新命令,然后发送至对应的Agent中
|
||||
*/
|
||||
public void buildXrayUpdateCommandAndCallAgent(Collection<ProxyNode> allProxyNodeList) {
|
||||
|
||||
String formatTimeString = TimeUtils.currentFormatTimeString();
|
||||
|
||||
List<String> resultKeyList = networkPathList
|
||||
List<String> 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
|
||||
);
|
||||
|
||||
@@ -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<VmessShare> vmessShareList) {
|
||||
|
||||
Base64.Encoder encoder = Base64.getEncoder();
|
||||
|
||||
List<String> 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<String> 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(
|
||||
|
||||
@@ -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<List<ProxyNode>> transformProxyChainString(List<String> proxyChainList, boolean isTopicName);
|
||||
|
||||
|
||||
/**
|
||||
* 根据代理链生成XrayConfig配置文件和订阅信息文件
|
||||
* Config配置会返回, 订阅不会返回
|
||||
* Config和Subscribe都会被持久化,并且上传至OSS中,订阅地址为固定的地址
|
||||
*
|
||||
* @param allNetworkPathList 完整的代理链
|
||||
* @return
|
||||
*/
|
||||
List<XrayConfigInfo> generateXrayConfigFromNodeList(List<List<ProxyNode>> allNetworkPathList);
|
||||
|
||||
|
||||
@@ -28,4 +38,21 @@ public interface XrayCoreService {
|
||||
*/
|
||||
HashMap<String, ProxyNode> manualUpdateProxyNodeListCache();
|
||||
|
||||
|
||||
/**
|
||||
* 根据代理链的配置生成订阅地址
|
||||
*
|
||||
* @param allNetworkPathList
|
||||
* @param chainPortMap
|
||||
*/
|
||||
List<VmessShare> generateSubscribeString(List<List<ProxyNode>> allNetworkPathList, HashMap<String, Integer> chainPortMap);
|
||||
|
||||
/**
|
||||
* [实际完整流程] - 根据代理链生成XrayConfig配置文件和订阅信息文件
|
||||
* <p>
|
||||
* Config配置会返回, 订阅不会返回
|
||||
* Config和Subscribe都会被持久化,并且上传至OSS中,订阅地址为固定的地址
|
||||
*/
|
||||
List<XrayConfigInfo> ProxyChainUpdateProcedure(List<String> proxyChainList, boolean isTopicName);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<ProxyNode> getAllProxyNodeSet(List<List<ProxyNode>> allNetworkPathList, boolean includeSubscribeNode) {
|
||||
// 拿到所有的proxyNode
|
||||
Set<ProxyNode> 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<List<ProxyNode>> transformProxyChainString(List<String> 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<ProxyNode, XrayConfig> resultMap = new HashMap<>();
|
||||
|
||||
// 清除tmp目录时候使用的一个锁
|
||||
|
||||
int currentVersion = cleanVersion.get();
|
||||
|
||||
// 记录每条代理链的端口号
|
||||
HashMap<String, Integer> 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<VmessShare> vmessShareList = generateSubscribeString(
|
||||
allNetworkPathList,
|
||||
chainPortMap
|
||||
);
|
||||
|
||||
// 拿到所有的proxyNode
|
||||
Set<ProxyNode> proxyNodeSet = allNetworkPathList
|
||||
.stream()
|
||||
.flatMap(
|
||||
networkPathList -> networkPathList.stream()
|
||||
)
|
||||
.collect(Collectors.toSet());
|
||||
log.debug(
|
||||
"vmessShareList is => {}",
|
||||
vmessShareList
|
||||
);
|
||||
|
||||
// 开始持久化订阅
|
||||
xrayConfigPersistor.subPersist(vmessShareList);
|
||||
|
||||
Set<ProxyNode> 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<ProxyNode> networkPathList, int currentVersion) {
|
||||
@Override
|
||||
public List<VmessShare> generateSubscribeString(List<List<ProxyNode>> allNetworkPathList, HashMap<String, Integer> chainPortMap) {
|
||||
|
||||
// 运行到此时,说明配置文件已经生成了, 根据每条链生成订阅定西
|
||||
return allNetworkPathList
|
||||
.stream()
|
||||
.map(
|
||||
networkPathList -> {
|
||||
|
||||
// 每条链需要生成相应的唯一标识
|
||||
String chainTag = generatePathTag(networkPathList);
|
||||
|
||||
// 拿到每条链的头节点
|
||||
ProxyNode headNode = networkPathList.get(0);
|
||||
|
||||
List<InboundObject> 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<XrayConfigInfo> ProxyChainUpdateProcedure(List<String> proxyChainList, boolean isTopicName) {
|
||||
|
||||
// 解析得到全部的节点
|
||||
List<List<ProxyNode>> allProxyChainNodeList = this.transformProxyChainString(
|
||||
proxyChainList,
|
||||
isTopicName
|
||||
);
|
||||
|
||||
// 生成所有的配置
|
||||
List<XrayConfigInfo> xrayConfigInfoList = this.generateXrayConfigFromNodeList(allProxyChainNodeList);
|
||||
|
||||
// 获取到全部的节点
|
||||
Set<ProxyNode> 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<ProxyNode> 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<ProxyNode> networkPathList, int pos) {
|
||||
private XrayConfig doBuildXrayConfig(String chainTag, ClientObject clientObject, int chainPort, List<ProxyNode> 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<RuleObject> ruleObjectList = routingObject.getRules();
|
||||
@@ -265,7 +448,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
||||
ruleObjectList.add(ruleObject);
|
||||
}
|
||||
|
||||
private void buildOutbound(XrayConfig xrayConfig, List<ProxyNode> networkPathList, int pos, ClientObject clientObject, String tag, Integer chainPort) {
|
||||
private void buildOutbound(XrayConfig xrayConfig, List<ProxyNode> networkPathList, int pos, ClientObject clientObject, String chainTag, Integer chainPort) {
|
||||
|
||||
// 从缓存中获取
|
||||
List<OutboundObject> 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<InboundObject> 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("->");
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user