[server][xary] - 完成实际Xray配置更新的全流程
This commit is contained in:
@@ -14,6 +14,14 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
<option name="sourceFilePath" value="server/Dockerfile-shanghai-remote-idea"/>
|
<option name="sourceFilePath" value="server/Dockerfile-shanghai-remote-idea"/>
|
||||||
|
<option name="volumeBindings">
|
||||||
|
<list>
|
||||||
|
<DockerVolumeBindingImpl>
|
||||||
|
<option name="containerPath" value="/octopus-server"/>
|
||||||
|
<option name="hostPath" value="/octopus-server"/>
|
||||||
|
</DockerVolumeBindingImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
</settings>
|
</settings>
|
||||||
</deployment>
|
</deployment>
|
||||||
<method v="2">
|
<method v="2">
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package io.wdd.common.utils;
|
package io.wdd.common.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -24,6 +26,15 @@ public class TimeUtils {
|
|||||||
|
|
||||||
private static final Map<String, Long> times = new LinkedHashMap<>();
|
private static final Map<String, Long> 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 {
|
static {
|
||||||
times.put(
|
times.put(
|
||||||
"year",
|
"year",
|
||||||
@@ -59,7 +70,7 @@ public class TimeUtils {
|
|||||||
|
|
||||||
byte[] timeBytes = LocalDateTime
|
byte[] timeBytes = LocalDateTime
|
||||||
.now(SYSTEM_TIME_ZONE_ID)
|
.now(SYSTEM_TIME_ZONE_ID)
|
||||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT))
|
||||||
.getBytes(StandardCharsets.UTF_8);
|
.getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
return ByteBuffer.wrap(timeBytes);
|
return ByteBuffer.wrap(timeBytes);
|
||||||
@@ -70,12 +81,34 @@ public class TimeUtils {
|
|||||||
return LocalDateTime.now(SYSTEM_TIME_ZONE_ID);
|
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 格式化 去掉时间中的毫秒数
|
* @return 格式化 去掉时间中的毫秒数
|
||||||
*/
|
*/
|
||||||
public static LocalDateTime currentFormatTime() {
|
public static LocalDateTime currentFormatTime() {
|
||||||
|
|
||||||
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT);
|
||||||
|
|
||||||
String format = LocalDateTime
|
String format = LocalDateTime
|
||||||
.now(SYSTEM_TIME_ZONE_ID)
|
.now(SYSTEM_TIME_ZONE_ID)
|
||||||
@@ -92,7 +125,7 @@ public class TimeUtils {
|
|||||||
public static String currentFormatTimeString() {
|
public static String currentFormatTimeString() {
|
||||||
|
|
||||||
return currentFormatTime()
|
return currentFormatTime()
|
||||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"));
|
.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocalDateTime cvFromDate(Date date) {
|
public static LocalDateTime cvFromDate(Date date) {
|
||||||
@@ -113,7 +146,7 @@ public class TimeUtils {
|
|||||||
|
|
||||||
return LocalDateTime
|
return LocalDateTime
|
||||||
.now(SYSTEM_TIME_ZONE_ID)
|
.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
|
return LocalDateTime
|
||||||
.now(SYSTEM_TIME_ZONE_ID)
|
.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) {
|
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) {
|
public static String toRelative(long duration, int maxLevel) {
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ import io.swagger.annotations.ApiParam;
|
|||||||
import io.wdd.common.beans.response.R;
|
import io.wdd.common.beans.response.R;
|
||||||
import io.wdd.func.xray.beans.node.ProxyNode;
|
import io.wdd.func.xray.beans.node.ProxyNode;
|
||||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
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 io.wdd.func.xray.service.XrayCoreService;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
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
|
@RestController
|
||||||
@RequestMapping("/server/func/xray")
|
@RequestMapping("/server/func/xray")
|
||||||
@@ -25,7 +26,7 @@ public class XrayController {
|
|||||||
XrayCoreService xrayCoreService;
|
XrayCoreService xrayCoreService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
XrayConfigDistribute xrayConfigDistribute;
|
XrayCallAgent xrayCallAgent;
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/chain/transform")
|
@PostMapping("/chain/transform")
|
||||||
@@ -47,7 +48,7 @@ public class XrayController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/chain/debug")
|
@PostMapping("/chain/debug")
|
||||||
@ApiOperation("[解析] - 代理链完整配置")
|
@ApiOperation("[解析] - debug 代理链完整配置")
|
||||||
public R<List<XrayConfigInfo>> debugProxyChainString(
|
public R<List<XrayConfigInfo>> debugProxyChainString(
|
||||||
@ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔")
|
@ApiParam(name = "proxyChainList", value = "代理链字符串,seoul2->tokyo2, 多条链使用,分隔")
|
||||||
@RequestParam("proxyChainList") List<String> proxyChainList,
|
@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")
|
@PostMapping("/cache/manual")
|
||||||
@ApiOperation("[缓存] - 手动更新代理链缓存")
|
@ApiOperation("[缓存] - 手动更新代理链缓存")
|
||||||
public R<HashMap<String, ProxyNode>> manualUpdateProxyNodeListCache() {
|
public R<HashMap<String, ProxyNode>> manualUpdateProxyNodeListCache() {
|
||||||
@@ -83,7 +101,7 @@ public class XrayController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/test")
|
/*@GetMapping("/test")
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
||||||
List<List<ProxyNode>> allNetworkPathList = new ArrayList<>();
|
List<List<ProxyNode>> allNetworkPathList = new ArrayList<>();
|
||||||
@@ -132,11 +150,11 @@ public class XrayController {
|
|||||||
|
|
||||||
xrayCoreService.generateXrayConfigFromNodeList(allNetworkPathList);
|
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() 结束!");
|
System.out.println("Xray controller test() 结束!");
|
||||||
|
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ public class OSSConfiguration {
|
|||||||
*/
|
*/
|
||||||
public static final List<OssConfig> ALL_OSS_CONFIG = new ArrayList<>();
|
public static final List<OssConfig> ALL_OSS_CONFIG = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始数据
|
* 初始数据
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.wdd.func.oss.service;
|
package io.wdd.func.oss.service;
|
||||||
|
|
||||||
import com.amazonaws.services.s3.AmazonS3;
|
|
||||||
import io.wdd.func.oss.config.OssConfig;
|
import io.wdd.func.oss.config.OssConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -14,13 +13,18 @@ import static io.wdd.func.oss.config.OSSConfiguration.ALL_OSS_CONFIG;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象存储后端选择
|
* 对象存储后端选择
|
||||||
* 指定一系列的策略,选出最为合适的OSS存储后端位置
|
* 指定一系列的策略,选出最为合适的OSS存储后端位置
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class OssBackendSelect {
|
public class OssBackendSelect {
|
||||||
|
|
||||||
public OssConfig one(String BackendPrefixName){
|
/**
|
||||||
|
* 根据 OSS桶的名称前缀 返回一个桶
|
||||||
|
* @param BackendPrefixName OSS桶的名称前缀
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OssConfig one(String BackendPrefixName) {
|
||||||
|
|
||||||
if (StringUtils.isEmpty(BackendPrefixName)) {
|
if (StringUtils.isEmpty(BackendPrefixName)) {
|
||||||
return oneRandom();
|
return oneRandom();
|
||||||
@@ -41,8 +45,10 @@ public class OssBackendSelect {
|
|||||||
// 随机选择一个, 也算是一个算法吧
|
// 随机选择一个, 也算是一个算法吧
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int pos = random
|
int pos = random
|
||||||
.ints(0,
|
.ints(
|
||||||
ossConfigList.size())
|
0,
|
||||||
|
ossConfigList.size()
|
||||||
|
)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.getAsInt();
|
.getAsInt();
|
||||||
|
|
||||||
@@ -50,20 +56,31 @@ public class OssBackendSelect {
|
|||||||
return ossConfigList.get(pos);
|
return ossConfigList.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 返回 随意一个桶
|
||||||
|
*/
|
||||||
public OssConfig oneRandom() {
|
public OssConfig oneRandom() {
|
||||||
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
int pos = random
|
int pos = random
|
||||||
.ints(0,
|
.ints(
|
||||||
ALL_OSS_CONFIG.size())
|
0,
|
||||||
|
ALL_OSS_CONFIG.size()
|
||||||
|
)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.getAsInt();
|
.getAsInt();
|
||||||
|
|
||||||
return ALL_OSS_CONFIG.get(pos);
|
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
|
return ALL_OSS_CONFIG
|
||||||
.stream()
|
.stream()
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class TcpHttpHeaderTemplate {
|
|||||||
"/news/",
|
"/news/",
|
||||||
"/finance/",
|
"/finance/",
|
||||||
"/sports/",
|
"/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.ProxyNodeType;
|
||||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
||||||
import io.wdd.server.beans.vo.ServerInfoVO;
|
import io.wdd.server.beans.vo.ServerInfoVO;
|
||||||
import io.wdd.server.coreService.CoreAppService;
|
|
||||||
import io.wdd.server.coreService.CoreServerService;
|
import io.wdd.server.coreService.CoreServerService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -29,8 +28,6 @@ public class XrayDBOperator {
|
|||||||
@Resource
|
@Resource
|
||||||
CoreServerService coreServerService;
|
CoreServerService coreServerService;
|
||||||
|
|
||||||
@Resource
|
|
||||||
CoreAppService coreAppService;
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void cache() {
|
public void cache() {
|
||||||
@@ -50,7 +47,6 @@ public class XrayDBOperator {
|
|||||||
|
|
||||||
transferServerInfoToProxyNode(serverInfoVOList);
|
transferServerInfoToProxyNode(serverInfoVOList);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transferServerInfoToProxyNode(List<ServerInfoVO> 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
|
//help gc
|
||||||
bitmap = null;
|
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) {
|
private ProxyNodeType convertNodeType(Integer proxyType) {
|
||||||
|
|
||||||
if (null == 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;
|
package io.wdd.func.xray.persisit.cache;
|
||||||
|
|
||||||
import io.wdd.func.xray.beans.node.Edge;
|
//public class EdgeWeightCache {
|
||||||
|
//
|
||||||
import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*;
|
//
|
||||||
|
// public static Edge chengduToShanghai;
|
||||||
public class EdgeWeightCache {
|
//
|
||||||
|
// public static Edge shanghaiToSeoul2;
|
||||||
|
// public static Edge shanghaiToTokyo2;
|
||||||
public static Edge chengduToShanghai;
|
//
|
||||||
|
// public static Edge hongkongToSeoul2;
|
||||||
public static Edge shanghaiToSeoul2;
|
// public static Edge hongkongToTokyo2;
|
||||||
public static Edge shanghaiToTokyo2;
|
// public static Edge hongkongToPhoenix2;
|
||||||
|
//
|
||||||
public static Edge hongkongToSeoul2;
|
// public static Edge seoul2ToTokyo2;
|
||||||
public static Edge hongkongToTokyo2;
|
// public static Edge seoul2ToPhoenix2;
|
||||||
public static Edge hongkongToPhoenix2;
|
// public static Edge seoul2ToLondon2;
|
||||||
|
//
|
||||||
public static Edge seoul2ToTokyo2;
|
// public static Edge tokyo2ToPhoenix2;
|
||||||
public static Edge seoul2ToPhoenix2;
|
// public static Edge tokyo2ToLondon2;
|
||||||
public static Edge seoul2ToLondon2;
|
//
|
||||||
|
// /**
|
||||||
public static Edge tokyo2ToPhoenix2;
|
// * 计算 网络路径中的路径权重
|
||||||
public static Edge tokyo2ToLondon2;
|
// * 值的范围在0-100,数字越小表示阻力越小
|
||||||
|
// * 指标 1.延迟 2.丢包率 3.带宽 4.节点稳定性
|
||||||
/**
|
// */
|
||||||
* 计算 网络路径中的路径权重
|
// public void EdgeWeightCalculate(){
|
||||||
* 值的范围在0-100,数字越小表示阻力越小
|
//
|
||||||
* 指标 1.延迟 2.丢包率 3.带宽 4.节点稳定性
|
//
|
||||||
*/
|
//
|
||||||
public void EdgeWeightCalculate(){
|
// }
|
||||||
|
//
|
||||||
|
// static {
|
||||||
|
//
|
||||||
}
|
// chengduToShanghai = new Edge(
|
||||||
|
// chengdu,
|
||||||
static {
|
// shanghai,
|
||||||
|
// 10
|
||||||
chengduToShanghai = new Edge(
|
// );
|
||||||
chengdu,
|
//
|
||||||
shanghai,
|
// shanghaiToSeoul2 = new Edge(
|
||||||
10
|
// shanghai,
|
||||||
);
|
// seoul2,
|
||||||
|
// 40
|
||||||
shanghaiToSeoul2 = new Edge(
|
// );
|
||||||
shanghai,
|
//
|
||||||
seoul2,
|
// shanghaiToTokyo2 = new Edge(
|
||||||
40
|
// shanghai,
|
||||||
);
|
// tokyo2,
|
||||||
|
// 60
|
||||||
shanghaiToTokyo2 = new Edge(
|
// );
|
||||||
shanghai,
|
//
|
||||||
tokyo2,
|
// seoul2ToTokyo2 = new Edge(
|
||||||
60
|
// seoul2,
|
||||||
);
|
// tokyo2,
|
||||||
|
// 10
|
||||||
seoul2ToTokyo2 = new Edge(
|
// );
|
||||||
seoul2,
|
// tokyo2ToPhoenix2 = new Edge(
|
||||||
tokyo2,
|
// tokyo2,
|
||||||
10
|
// phoenix2,
|
||||||
);
|
// 30
|
||||||
tokyo2ToPhoenix2 = new Edge(
|
// );
|
||||||
tokyo2,
|
// tokyo2ToLondon2 = new Edge(
|
||||||
phoenix2,
|
// tokyo2,
|
||||||
30
|
// london2,
|
||||||
);
|
// 50
|
||||||
tokyo2ToLondon2 = new Edge(
|
// );
|
||||||
tokyo2,
|
// hongkongToTokyo2 = new Edge(
|
||||||
london2,
|
// hongkong,
|
||||||
50
|
// tokyo2,
|
||||||
);
|
// 40
|
||||||
hongkongToTokyo2 = new Edge(
|
// );
|
||||||
hongkong,
|
// hongkongToSeoul2 = new Edge(
|
||||||
tokyo2,
|
// hongkong,
|
||||||
40
|
// seoul2,
|
||||||
);
|
// 20
|
||||||
hongkongToSeoul2 = new Edge(
|
// );
|
||||||
hongkong,
|
//
|
||||||
seoul2,
|
// }
|
||||||
20
|
//}
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package io.wdd.func.xray.persisit.cache;
|
package io.wdd.func.xray.persisit.cache;
|
||||||
|
|
||||||
import io.wdd.func.xray.beans.node.ProxyNode;
|
import io.wdd.func.xray.beans.node.ProxyNode;
|
||||||
import io.wdd.func.xray.beans.node.ProxyNodeType;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
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 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 final String SUBSCRIBE_NODE_NAME = "SUBSCRIBE";
|
||||||
public static ProxyNode tokyo2;
|
|
||||||
public static ProxyNode phoenix2;
|
|
||||||
public static ProxyNode london2;
|
|
||||||
|
|
||||||
// 开发使用
|
private static ProxyNode chengdu;
|
||||||
public static ProxyNode chengduAgent;
|
private static ProxyNode shanghai;
|
||||||
public static ProxyNode tokyoDev;
|
private static ProxyNode hongkong;
|
||||||
public static ProxyNode seoul5;
|
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
|
chengdu = ProxyNode
|
||||||
.builder()
|
.builder()
|
||||||
@@ -185,6 +189,6 @@ public class ProxyNodeCache {
|
|||||||
seoul5
|
seoul5
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,7 @@ package io.wdd.func.xray.service;
|
|||||||
|
|
||||||
import io.wdd.common.utils.TimeUtils;
|
import io.wdd.common.utils.TimeUtils;
|
||||||
import io.wdd.func.oss.config.OctopusObjectSummary;
|
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.ProxyNode;
|
||||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
|
||||||
import io.wdd.rpc.execute.service.AsyncExecutionService;
|
import io.wdd.rpc.execute.service.AsyncExecutionService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -14,6 +10,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -27,7 +24,7 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class XrayConfigDistribute {
|
public class XrayCallAgent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 存储更新 Xray的命令行
|
* 存储更新 Xray的命令行
|
||||||
@@ -41,24 +38,6 @@ public class XrayConfigDistribute {
|
|||||||
|
|
||||||
static {
|
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<>(
|
ArrayList<String> first = new ArrayList<>(
|
||||||
List.of(
|
List.of(
|
||||||
"mv",
|
"mv",
|
||||||
@@ -70,7 +49,7 @@ public class XrayConfigDistribute {
|
|||||||
ArrayList<String> second = new ArrayList<>(
|
ArrayList<String> second = new ArrayList<>(
|
||||||
List.of(
|
List.of(
|
||||||
"wget",
|
"wget",
|
||||||
"url",
|
"AGENT_SPECIFIC_CONFIG_URL",
|
||||||
"-O",
|
"-O",
|
||||||
"/usr/local/etc/xray/config.json"
|
"/usr/local/etc/xray/config.json"
|
||||||
)
|
)
|
||||||
@@ -96,7 +75,6 @@ public class XrayConfigDistribute {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
updateXrayCommandList.add(first);
|
updateXrayCommandList.add(first);
|
||||||
updateXrayCommandList.add(second);
|
updateXrayCommandList.add(second);
|
||||||
updateXrayCommandList.add(third);
|
updateXrayCommandList.add(third);
|
||||||
@@ -104,49 +82,17 @@ public class XrayConfigDistribute {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
OssBackendSelect ossBackendSelect;
|
|
||||||
@Resource
|
|
||||||
OSSCoreService ossCoreService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
AsyncExecutionService executionService;
|
AsyncExecutionService executionService;
|
||||||
|
|
||||||
public void uploadXrayConfigToOSS(List<ProxyNode> networkPathList) {
|
/**
|
||||||
|
* 为代理链的每一个节点 构建Xray配置更新命令,然后发送至对应的Agent中
|
||||||
// 所有的文件全部存储至一个对象存储的后端中
|
*/
|
||||||
OssConfig ossConfig = ossBackendSelect.oneRandom();
|
public void buildXrayUpdateCommandAndCallAgent(Collection<ProxyNode> allProxyNodeList) {
|
||||||
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) {
|
|
||||||
|
|
||||||
String formatTimeString = TimeUtils.currentFormatTimeString();
|
String formatTimeString = TimeUtils.currentFormatTimeString();
|
||||||
|
|
||||||
List<String> resultKeyList = networkPathList
|
List<String> resultKeyList = allProxyNodeList
|
||||||
.stream()
|
.stream()
|
||||||
.map(
|
.map(
|
||||||
proxyNode -> {
|
proxyNode -> {
|
||||||
@@ -190,7 +136,9 @@ public class XrayConfigDistribute {
|
|||||||
updateCommandType,
|
updateCommandType,
|
||||||
null,
|
null,
|
||||||
updateXrayCommandList,
|
updateXrayCommandList,
|
||||||
null
|
false,
|
||||||
|
null,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
return resultKey;
|
return resultKey;
|
||||||
@@ -199,7 +147,7 @@ public class XrayConfigDistribute {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
"发送所有的配置到各个Agent成功, 结果查看为 => {}",
|
"为代理链的每一个节点 构建Xray配置更新命令,然后发送至对应的Agent中成功, 结果查看为 => {}",
|
||||||
resultKeyList
|
resultKeyList
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -8,10 +8,10 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||||
import io.wdd.common.handler.MyRuntimeException;
|
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.ProxyNode;
|
||||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
||||||
import io.wdd.func.xray.beans.xray.XrayConfig;
|
import io.wdd.func.xray.beans.xray.XrayConfig;
|
||||||
|
import io.wdd.func.xray.beans.xray.share.VmessShare;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
@@ -22,7 +22,15 @@ import java.io.BufferedWriter;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
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.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
|
* 获取rerouces目录 https://blog.csdn.net/pengpengpeng85/article/details/84785575
|
||||||
@@ -34,6 +42,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
@Service
|
@Service
|
||||||
public class XrayConfigPersistor {
|
public class XrayConfigPersistor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XRAY端口的起始位置
|
||||||
|
*/
|
||||||
|
public static final int XRAY_PORT_MAX = 20000;
|
||||||
// 参考 https://github.com/FasterXML/jackson-databind/issues/585
|
// 参考 https://github.com/FasterXML/jackson-databind/issues/585
|
||||||
private static final ObjectWriter objectWriter = new ObjectMapper()
|
private static final ObjectWriter objectWriter = new ObjectMapper()
|
||||||
// 忽略掉 null的字段
|
// 忽略掉 null的字段
|
||||||
@@ -46,10 +58,11 @@ public class XrayConfigPersistor {
|
|||||||
.withLinefeed("\n")
|
.withLinefeed("\n")
|
||||||
));
|
));
|
||||||
private static final String XrayResultPathPrefix = "xrayResult/";
|
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的临时文件目录
|
* 存储生成的Xray Config的临时文件目录
|
||||||
*/
|
*/
|
||||||
@@ -94,6 +107,7 @@ public class XrayConfigPersistor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中
|
* 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中
|
||||||
*
|
*
|
||||||
@@ -117,7 +131,7 @@ public class XrayConfigPersistor {
|
|||||||
.writeValueAsString(xrayConfig);
|
.writeValueAsString(xrayConfig);
|
||||||
|
|
||||||
// 获得到文件名称
|
// 获得到文件名称
|
||||||
String timeString = TimeUtils.currentFormatTimeString();
|
String timeString = UniformFormatTimeString();
|
||||||
String fileName = buildXrayConfigFileName(
|
String fileName = buildXrayConfigFileName(
|
||||||
proxyNode,
|
proxyNode,
|
||||||
timeString
|
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) {
|
private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) {
|
||||||
|
|
||||||
return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json";
|
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) {
|
private File write(String fileName, String content, int currentVersion) {
|
||||||
|
|
||||||
log.debug(
|
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.ProxyNode;
|
||||||
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
import io.wdd.func.xray.beans.node.XrayConfigInfo;
|
||||||
|
import io.wdd.func.xray.beans.xray.share.VmessShare;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface XrayCoreService {
|
public interface XrayCoreService {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析代理链字符串,返回完整的代理列表
|
* 解析代理链字符串,返回完整的代理列表
|
||||||
*
|
*
|
||||||
@@ -18,6 +20,14 @@ public interface XrayCoreService {
|
|||||||
List<List<ProxyNode>> transformProxyChainString(List<String> proxyChainList, boolean isTopicName);
|
List<List<ProxyNode>> transformProxyChainString(List<String> proxyChainList, boolean isTopicName);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据代理链生成XrayConfig配置文件和订阅信息文件
|
||||||
|
* Config配置会返回, 订阅不会返回
|
||||||
|
* Config和Subscribe都会被持久化,并且上传至OSS中,订阅地址为固定的地址
|
||||||
|
*
|
||||||
|
* @param allNetworkPathList 完整的代理链
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
List<XrayConfigInfo> generateXrayConfigFromNodeList(List<List<ProxyNode>> allNetworkPathList);
|
List<XrayConfigInfo> generateXrayConfigFromNodeList(List<List<ProxyNode>> allNetworkPathList);
|
||||||
|
|
||||||
|
|
||||||
@@ -28,4 +38,21 @@ public interface XrayCoreService {
|
|||||||
*/
|
*/
|
||||||
HashMap<String, ProxyNode> manualUpdateProxyNodeListCache();
|
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.inbound.vmess.VMESS;
|
||||||
import io.wdd.func.xray.beans.xray.protocol.outbound.Freedom;
|
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.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.InboundObject;
|
||||||
import io.wdd.func.xray.beans.xray.transport.OutboundObject;
|
import io.wdd.func.xray.beans.xray.transport.OutboundObject;
|
||||||
import io.wdd.func.xray.persisit.XrayDBOperator;
|
import io.wdd.func.xray.persisit.XrayDBOperator;
|
||||||
|
import io.wdd.func.xray.persisit.XrayOssOperator;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.beanutils.BeanUtils;
|
import org.apache.commons.beanutils.BeanUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
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.InboundVmessHTTPTemplateClass.ListenAddress;
|
||||||
import static io.wdd.func.xray.beans.config.LogTemplateClass.LogTemplate;
|
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.beans.config.OutboundVmessHTTPTemplateClass.*;
|
||||||
import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_MAP;
|
import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.*;
|
||||||
import static io.wdd.func.xray.persisit.cache.ProxyNodeCache.PROXY_NODE_TOPIC_NAME_MAP;
|
|
||||||
import static io.wdd.func.xray.service.XrayConfigPersistor.*;
|
import static io.wdd.func.xray.service.XrayConfigPersistor.*;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -42,6 +45,38 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
@Resource
|
@Resource
|
||||||
XrayDBOperator xrayDBOperator;
|
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
|
@Override
|
||||||
public List<List<ProxyNode>> transformProxyChainString(List<String> proxyChainList, boolean isTopicName) {
|
public List<List<ProxyNode>> transformProxyChainString(List<String> proxyChainList, boolean isTopicName) {
|
||||||
|
|
||||||
@@ -54,11 +89,19 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
// 此处获取到的就是 每一个节点的名称
|
// 此处获取到的就是 每一个节点的名称
|
||||||
// AgentName 或者 AgentTopicName
|
// AgentName 或者 AgentTopicName
|
||||||
agentKindOfName -> {
|
agentKindOfName -> {
|
||||||
|
ProxyNode targetNode = null;
|
||||||
|
|
||||||
if (isTopicName) {
|
if (isTopicName) {
|
||||||
return PROXY_NODE_TOPIC_NAME_MAP.get(agentKindOfName);
|
targetNode = PROXY_NODE_TOPIC_NAME_MAP.get(agentKindOfName);
|
||||||
} else {
|
} else {
|
||||||
return PROXY_NODE_MAP.get(agentKindOfName);
|
targetNode = PROXY_NODE_MAP.get(agentKindOfName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert.notNull(
|
||||||
|
targetNode,
|
||||||
|
"输入的代理链字符串有误! 请检查! => " + agentKindOfName
|
||||||
|
);
|
||||||
|
return targetNode;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
@@ -92,30 +135,60 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
// HashMap<ProxyNode, XrayConfig> resultMap = new HashMap<>();
|
// HashMap<ProxyNode, XrayConfig> resultMap = new HashMap<>();
|
||||||
|
|
||||||
// 清除tmp目录时候使用的一个锁
|
// 清除tmp目录时候使用的一个锁
|
||||||
|
|
||||||
int currentVersion = cleanVersion.get();
|
int currentVersion = cleanVersion.get();
|
||||||
|
|
||||||
|
// 记录每条代理链的端口号
|
||||||
|
HashMap<String, Integer> chainPortMap = new HashMap<>();
|
||||||
|
|
||||||
|
// 需要事先清空缓存
|
||||||
|
manualUpdateProxyNodeListCache();
|
||||||
|
|
||||||
|
// 生成代理链
|
||||||
allNetworkPathList
|
allNetworkPathList
|
||||||
.stream()
|
.stream()
|
||||||
.forEach(
|
.forEach(
|
||||||
networkPathList -> {
|
networkPathList -> {
|
||||||
|
// 为每一条链生成端口
|
||||||
int chainPort = XRAY_PORT_POOL.decrementAndGet();
|
int chainPort = XRAY_PORT_POOL.decrementAndGet();
|
||||||
|
|
||||||
|
// 为每条链生成相应的tag
|
||||||
|
// 形式为 Shanghai-amd64-01->Seoul-amd64-04
|
||||||
|
String chainTag = generatePathTag(networkPathList);
|
||||||
|
|
||||||
|
// 每条链单独生成Xray Config配置文件
|
||||||
generateXrayJsonSinglePath(
|
generateXrayJsonSinglePath(
|
||||||
chainPort,
|
chainPort,
|
||||||
networkPathList,
|
networkPathList,
|
||||||
currentVersion
|
currentVersion,
|
||||||
|
chainTag
|
||||||
|
);
|
||||||
|
|
||||||
|
// 为每条代理链 缓存 对应端口
|
||||||
|
chainPortMap.put(
|
||||||
|
chainTag,
|
||||||
|
chainPort
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 生成订阅地址链接
|
||||||
|
List<VmessShare> vmessShareList = generateSubscribeString(
|
||||||
|
allNetworkPathList,
|
||||||
|
chainPortMap
|
||||||
|
);
|
||||||
|
|
||||||
// 拿到所有的proxyNode
|
log.debug(
|
||||||
Set<ProxyNode> proxyNodeSet = allNetworkPathList
|
"vmessShareList is => {}",
|
||||||
.stream()
|
vmessShareList
|
||||||
.flatMap(
|
);
|
||||||
networkPathList -> networkPathList.stream()
|
|
||||||
)
|
// 开始持久化订阅
|
||||||
.collect(Collectors.toSet());
|
xrayConfigPersistor.subPersist(vmessShareList);
|
||||||
|
|
||||||
|
Set<ProxyNode> proxyNodeSet = getAllProxyNodeSet(
|
||||||
|
allNetworkPathList,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// 返回所有的配置
|
// 返回所有的配置
|
||||||
return proxyNodeSet
|
return proxyNodeSet
|
||||||
@@ -139,13 +212,123 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
return PROXY_NODE_TOPIC_NAME_MAP;
|
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();
|
int pathLength = networkPathList.size();
|
||||||
|
|
||||||
// 采用 VMESS + websocket的形式形成 链状代理
|
// 采用 VMESS + websocket的形式形成 链状代理
|
||||||
// 由于 Vlss+XTLS的形式形成 链状结构
|
// 由于 Vlss+XTLS的形式形成 链状结构
|
||||||
String tag = generatePathTag(networkPathList);
|
|
||||||
|
|
||||||
// 通用内容生成
|
// 通用内容生成
|
||||||
String uuid = UUID
|
String uuid = UUID
|
||||||
@@ -157,7 +340,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
.level(0)
|
.level(0)
|
||||||
// 为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD
|
// 为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD
|
||||||
.alterId(0)
|
.alterId(0)
|
||||||
.email(tag + "@octopus.io")
|
.email(chainTag + "@octopus.io")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
for (int pos = 0; pos < pathLength; pos++) {
|
for (int pos = 0; pos < pathLength; pos++) {
|
||||||
@@ -166,7 +349,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
|
|
||||||
// 构造 xrayConfig
|
// 构造 xrayConfig
|
||||||
XrayConfig xrayConfig = doBuildXrayConfig(
|
XrayConfig xrayConfig = doBuildXrayConfig(
|
||||||
tag,
|
chainTag,
|
||||||
clientObject,
|
clientObject,
|
||||||
chainPort,
|
chainPort,
|
||||||
networkPathList,
|
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基础上进行生成
|
// 需要从现有的XrayConfig基础上进行生成
|
||||||
// 尝试从 缓存层获取
|
// 尝试从 缓存层获取
|
||||||
@@ -205,7 +388,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
xrayConfig,
|
xrayConfig,
|
||||||
clientObject,
|
clientObject,
|
||||||
chainPort,
|
chainPort,
|
||||||
tag
|
chainTag
|
||||||
);
|
);
|
||||||
|
|
||||||
// 中间节点,需要有特定的输出
|
// 中间节点,需要有特定的输出
|
||||||
@@ -215,23 +398,23 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
networkPathList,
|
networkPathList,
|
||||||
pos,
|
pos,
|
||||||
clientObject,
|
clientObject,
|
||||||
tag,
|
chainTag,
|
||||||
chainPort
|
chainPort
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置 路由信息
|
// 设置 路由信息
|
||||||
buildRouting(
|
buildRouting(
|
||||||
xrayConfig,
|
xrayConfig,
|
||||||
tag
|
chainTag
|
||||||
);
|
);
|
||||||
|
|
||||||
return xrayConfig;
|
return xrayConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildOutboundFree(XrayConfig xrayConfig, String tag) {
|
private void buildOutboundFree(XrayConfig xrayConfig, String chainTag) {
|
||||||
|
|
||||||
OutboundObject freeOut = new Freedom();
|
OutboundObject freeOut = new Freedom();
|
||||||
freeOut.setTag(tag);
|
freeOut.setTag(chainTag);
|
||||||
|
|
||||||
xrayConfig.setOutbounds(new ArrayList<>(
|
xrayConfig.setOutbounds(new ArrayList<>(
|
||||||
List.of(freeOut)
|
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();
|
RoutingObject routingObject = xrayConfig.getRouting();
|
||||||
@@ -252,8 +435,8 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
RuleObject ruleObject = RuleObject
|
RuleObject ruleObject = RuleObject
|
||||||
.builder()
|
.builder()
|
||||||
.type("field")
|
.type("field")
|
||||||
.inboundTag(List.of(tag))
|
.inboundTag(List.of(chainTag))
|
||||||
.outboundTag(tag)
|
.outboundTag(chainTag)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
List<RuleObject> ruleObjectList = routingObject.getRules();
|
List<RuleObject> ruleObjectList = routingObject.getRules();
|
||||||
@@ -265,7 +448,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
ruleObjectList.add(ruleObject);
|
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();
|
List<OutboundObject> outboundObjectList = xrayConfig.getOutbounds();
|
||||||
@@ -302,7 +485,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置Tag信息
|
// 设置Tag信息
|
||||||
vmessOutbound.setTag(tag);
|
vmessOutbound.setTag(chainTag);
|
||||||
|
|
||||||
// 设置出口信息
|
// 设置出口信息
|
||||||
OutboundConfigurationObject.ServerObject serverObject = vmessOutbound
|
OutboundConfigurationObject.ServerObject serverObject = vmessOutbound
|
||||||
@@ -325,7 +508,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
outboundObjectList.add(vmessOutbound);
|
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();
|
List<InboundObject> inboundObjectList = xrayConfig.getInbounds();
|
||||||
@@ -345,7 +528,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
inboundObject.setTag(tag);
|
inboundObject.setTag(chainTag);
|
||||||
|
|
||||||
// todo port怎么办
|
// todo port怎么办
|
||||||
inboundObject.setPort(chainPort);
|
inboundObject.setPort(chainPort);
|
||||||
@@ -365,7 +548,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shanghai->seoul2->tokyo2
|
* Shanghai-amd64-01->Seoul-amd64-04
|
||||||
*
|
*
|
||||||
* @param networkPathList 网络路径节点
|
* @param networkPathList 网络路径节点
|
||||||
* @return 路径Tag
|
* @return 路径Tag
|
||||||
@@ -377,7 +560,7 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
.stream()
|
.stream()
|
||||||
.forEach(
|
.forEach(
|
||||||
networkPath -> {
|
networkPath -> {
|
||||||
sb.append(networkPath.getName());
|
sb.append(networkPath.getAgentName());
|
||||||
sb.append("->");
|
sb.append("->");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user