[server][ xray]- 优化Xray配置部分的代码
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Server-dev" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="Server-dev" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" activateToolWindowBeforeRun="false">
|
||||||
|
<option name="DEBUG_MODE" value="true"/>
|
||||||
<option name="HIDE_BANNER" value="true" />
|
<option name="HIDE_BANNER" value="true" />
|
||||||
<module name="server" />
|
<module name="server" />
|
||||||
<selectedOptions>
|
<selectedOptions>
|
||||||
<option name="spring.boot.profiles" visible="false" />
|
<option name="spring.boot.profiles" visible="false" />
|
||||||
</selectedOptions>
|
</selectedOptions>
|
||||||
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.ServerApplication" />
|
<option name="SPRING_BOOT_MAIN_CLASS" value="io.wdd.ServerApplication" />
|
||||||
<option name="VM_PARAMETERS" value="-Dfile.encoding=utf-8 -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev" />
|
<option name="VM_PARAMETERS"
|
||||||
|
value="-Ddebug=true -Dlogging.level.io.wdd.server=debug -Dfile.encoding=utf-8 -Dspring.profiles.active=dev -Dspring.cloud.nacos.config.group=dev -Dspring.cloud.nacos.config.extension-configs[0].dataId=common-dev.yaml -Dspring.cloud.nacos.config.extension-configs[0].group=dev"/>
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Make" enabled="true" />
|
<option name="Make" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
@@ -61,8 +61,15 @@ public class XrayController {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ArrayList<ProxyNode> pathE = new ArrayList<>(
|
||||||
|
Collections.singletonList(
|
||||||
|
seoul5
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// allNetworkPathList.add(pathA);
|
// allNetworkPathList.add(pathA);
|
||||||
allNetworkPathList.add(pathD);
|
// allNetworkPathList.add(pathD);
|
||||||
|
allNetworkPathList.add(pathE);
|
||||||
// allNetworkPathList.add(pathB);
|
// allNetworkPathList.add(pathB);
|
||||||
// allNetworkPathList.add(pathC);
|
// allNetworkPathList.add(pathC);
|
||||||
|
|
||||||
@@ -72,7 +79,7 @@ public class XrayController {
|
|||||||
|
|
||||||
xrayConfigDistribute.buildXrayUpdateResult(allNetworkPathList.get(0));
|
xrayConfigDistribute.buildXrayUpdateResult(allNetworkPathList.get(0));
|
||||||
|
|
||||||
System.out.println("结束!");
|
System.out.println("Xray controller test() 结束!");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class ProxyNodeSet {
|
|||||||
// 开发使用
|
// 开发使用
|
||||||
public static ProxyNode chengduAgent;
|
public static ProxyNode chengduAgent;
|
||||||
public static ProxyNode tokyoDev;
|
public static ProxyNode tokyoDev;
|
||||||
|
public static ProxyNode seoul5;
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -117,15 +118,58 @@ public class ProxyNodeSet {
|
|||||||
.agentTopicName("Chengdu-amd64-77-remote")
|
.agentTopicName("Chengdu-amd64-77-remote")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ProxyNodeMap.put(chengdu.getNum(), chengdu);
|
|
||||||
ProxyNodeMap.put(hongkong.getNum(), hongkong);
|
seoul5 = ProxyNode
|
||||||
ProxyNodeMap.put(shanghai.getNum(), shanghai);
|
.builder()
|
||||||
ProxyNodeMap.put(seoul2.getNum(), seoul2);
|
.location("Seoul")
|
||||||
ProxyNodeMap.put(tokyo2.getNum(), tokyo2);
|
.num(97)
|
||||||
ProxyNodeMap.put(phoenix2.getNum(), phoenix2);
|
.publicIPv4("146.56.159.175")
|
||||||
ProxyNodeMap.put(london2.getNum(), london2);
|
.proxyNodeType(ProxyNodeType.EXTERNAL)
|
||||||
ProxyNodeMap.put(chengduAgent.getNum(), chengduAgent);
|
.name("oracle-seoul5")
|
||||||
ProxyNodeMap.put(tokyoDev.getNum(), tokyoDev);
|
.agentName("Seoul-arm64-02")
|
||||||
|
.agentTopicName("Seoul-arm64-02-oracle")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
chengdu.getNum(),
|
||||||
|
chengdu
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
hongkong.getNum(),
|
||||||
|
hongkong
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
shanghai.getNum(),
|
||||||
|
shanghai
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
seoul2.getNum(),
|
||||||
|
seoul2
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
tokyo2.getNum(),
|
||||||
|
tokyo2
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
phoenix2.getNum(),
|
||||||
|
phoenix2
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
london2.getNum(),
|
||||||
|
london2
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
chengduAgent.getNum(),
|
||||||
|
chengduAgent
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
tokyoDev.getNum(),
|
||||||
|
tokyoDev
|
||||||
|
);
|
||||||
|
ProxyNodeMap.put(
|
||||||
|
seoul5.getNum(),
|
||||||
|
seoul5
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://xtls.github.io/config/inbounds/vmess.html#clientobject
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
package io.wdd.func.xray.service;
|
package io.wdd.func.xray.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||||
|
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.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 lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
@@ -15,22 +25,79 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取rerouces目录 https://blog.csdn.net/pengpengpeng85/article/details/84785575
|
* 获取rerouces目录 https://blog.csdn.net/pengpengpeng85/article/details/84785575
|
||||||
*
|
* <p>
|
||||||
* 写入文件的教程 https://cloud.tencent.com/developer/article/1895274
|
* 写入文件的教程 https://cloud.tencent.com/developer/article/1895274
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class XrayConfigPersistor {
|
public class XrayConfigPersistor {
|
||||||
|
|
||||||
private static String XrayResultPath = "xrayResult/";
|
// 参考 https://github.com/FasterXML/jackson-databind/issues/585
|
||||||
|
private static final ObjectWriter objectWriter = new ObjectMapper()
|
||||||
|
// 忽略掉 null的字段
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
// 写的文件必须是unix类型的分隔符号
|
||||||
|
.writer(
|
||||||
|
new DefaultPrettyPrinter()
|
||||||
|
.withObjectIndenter(
|
||||||
|
new DefaultIndenter()
|
||||||
|
.withLinefeed("\n")
|
||||||
|
));
|
||||||
|
private static final String XrayResultPath = "xrayResult/";
|
||||||
public static AtomicInteger cleanVersion = new AtomicInteger(0);
|
public static AtomicInteger cleanVersion = new AtomicInteger(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行Xray生成配置文件的持久化工作,沈成伟临时文件保存至当前目录中
|
||||||
|
*
|
||||||
|
* @param xrayConfig
|
||||||
|
* @param currentVersion
|
||||||
|
* @param proxyNode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public XrayConfigInfo persist(XrayConfig xrayConfig, int currentVersion, ProxyNode proxyNode) {
|
||||||
|
try {
|
||||||
|
// 将生成的xrayConfig直接写为字符串
|
||||||
|
String resultContent = objectWriter
|
||||||
|
.writeValueAsString(xrayConfig);
|
||||||
|
|
||||||
public File write(String fileName , String content, int currentVersion) {
|
// 获得到文件名称
|
||||||
|
String timeString = TimeUtils.currentFormatTimeString();
|
||||||
|
String fileName = buildXrayConfigFileName(
|
||||||
|
proxyNode,
|
||||||
|
timeString
|
||||||
|
);
|
||||||
|
|
||||||
System.out.println("currentVersion = " + currentVersion);
|
// 文件持久化!
|
||||||
|
File xrayConfigFile = write(
|
||||||
|
fileName,
|
||||||
|
resultContent,
|
||||||
|
currentVersion
|
||||||
|
);
|
||||||
|
|
||||||
|
// 文件写入完成,保存文件信息
|
||||||
|
XrayConfigInfo xrayConfigInfo = new XrayConfigInfo();
|
||||||
|
xrayConfigInfo.setXrayConfigFile(xrayConfigFile);
|
||||||
|
xrayConfigInfo.setXrayConfigFileName(fileName);
|
||||||
|
|
||||||
|
return xrayConfigInfo;
|
||||||
|
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) {
|
||||||
|
|
||||||
|
return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private File write(String fileName, String content, int currentVersion) {
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"currentVersion = {}",
|
||||||
|
currentVersion
|
||||||
|
);
|
||||||
|
|
||||||
if (cleanVersion.get() == currentVersion) {
|
if (cleanVersion.get() == currentVersion) {
|
||||||
// 清除旧的内容
|
// 清除旧的内容
|
||||||
@@ -41,29 +108,51 @@ public class XrayConfigPersistor {
|
|||||||
|
|
||||||
// 构造对象开始写入, 生成文件
|
// 构造对象开始写入, 生成文件
|
||||||
File resultFile = getResultFile(fileName);
|
File resultFile = getResultFile(fileName);
|
||||||
try {
|
|
||||||
|
|
||||||
log.debug("开始写入XrayConfig进入文件中,文件名为 => {}",fileName);
|
FileWriter fileWriter = null;
|
||||||
FileWriter fileWriter = new FileWriter(
|
BufferedWriter bufferedWriter = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug(
|
||||||
|
"开始写入XrayConfig进入文件中,文件名为 => {}",
|
||||||
|
fileName
|
||||||
|
);
|
||||||
|
fileWriter = new FileWriter(
|
||||||
resultFile
|
resultFile
|
||||||
);
|
);
|
||||||
BufferedWriter bufferedWriter = new BufferedWriter(
|
bufferedWriter = new BufferedWriter(
|
||||||
fileWriter
|
fileWriter
|
||||||
);
|
);
|
||||||
|
|
||||||
log.debug("文件内容为 => {}", content);
|
log.debug(
|
||||||
|
"文件内容为 => {}",
|
||||||
|
content
|
||||||
|
);
|
||||||
bufferedWriter.write(content);
|
bufferedWriter.write(content);
|
||||||
|
|
||||||
// must close
|
|
||||||
bufferedWriter.close();
|
|
||||||
fileWriter.close();
|
|
||||||
|
|
||||||
|
|
||||||
return resultFile;
|
return resultFile;
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("打开文件失败,写入tmp文件失败! 文件为 => {}", resultFile.getName());
|
log.error(
|
||||||
|
"打开文件失败,写入tmp文件失败! 文件为 => {}",
|
||||||
|
resultFile.getName()
|
||||||
|
);
|
||||||
throw new MyRuntimeException(e);
|
throw new MyRuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// must close
|
||||||
|
bufferedWriter.close();
|
||||||
|
fileWriter.close();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(
|
||||||
|
"关闭文件写入流失败!, 请检查 文件为 => [ {} ], 内容为 => {}",
|
||||||
|
fileName,
|
||||||
|
content
|
||||||
|
);
|
||||||
|
throw new MyRuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,11 +171,12 @@ public class XrayConfigPersistor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据文件名,需要创建一个文件
|
* 根据文件名,需要创建一个文件
|
||||||
|
*
|
||||||
* @param fileName 文件名,如 xxx.json
|
* @param fileName 文件名,如 xxx.json
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private File getResultFile(String fileName ){
|
private File getResultFile(String fileName) {
|
||||||
|
|
||||||
ClassPathResource classPathResource = new ClassPathResource(XrayResultPath);
|
ClassPathResource classPathResource = new ClassPathResource(XrayResultPath);
|
||||||
|
|
||||||
@@ -99,7 +189,10 @@ public class XrayConfigPersistor {
|
|||||||
);
|
);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("获取文件失败请检查! fileName is => {}", fileName);
|
log.error(
|
||||||
|
"获取文件失败请检查! fileName is => {}",
|
||||||
|
fileName
|
||||||
|
);
|
||||||
throw new MyRuntimeException(e);
|
throw new MyRuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package io.wdd.func.xray.service;
|
package io.wdd.func.xray.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
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.RoutingObject;
|
import io.wdd.func.xray.beans.xray.RoutingObject;
|
||||||
@@ -20,7 +16,6 @@ import org.apache.commons.beanutils.BeanUtils;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,13 +31,9 @@ import static io.wdd.func.xray.service.XrayConfigPersistor.cleanVersion;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class XrayCoreServiceImpl implements XrayCoreService {
|
public class XrayCoreServiceImpl implements XrayCoreService {
|
||||||
|
|
||||||
@Resource
|
|
||||||
ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
XrayConfigPersistor xrayConfigPersistor;
|
XrayConfigPersistor xrayConfigPersistor;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateXrayJsonFromNodeList(ArrayList<ArrayList<ProxyNode>> allNetworkPathList) {
|
public void generateXrayJsonFromNodeList(ArrayList<ArrayList<ProxyNode>> allNetworkPathList) {
|
||||||
|
|
||||||
@@ -81,9 +72,6 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
private void generateXrayJsonSinglePath(ArrayList<ProxyNode> networkPathList) {
|
private void generateXrayJsonSinglePath(ArrayList<ProxyNode> networkPathList) {
|
||||||
int pathLength = networkPathList.size();
|
int pathLength = networkPathList.size();
|
||||||
|
|
||||||
// 忽略掉 null的字段
|
|
||||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
|
||||||
|
|
||||||
// 采用 VMESS + websocket的形式形成 链状代理
|
// 采用 VMESS + websocket的形式形成 链状代理
|
||||||
// 由于 Vlss+XTLS的形式形成 链状结构
|
// 由于 Vlss+XTLS的形式形成 链状结构
|
||||||
String tag = generatePathTag(networkPathList);
|
String tag = generatePathTag(networkPathList);
|
||||||
@@ -97,7 +85,8 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
.builder()
|
.builder()
|
||||||
.id(uuid)
|
.id(uuid)
|
||||||
.level(0)
|
.level(0)
|
||||||
.alterId(23)
|
// 为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD
|
||||||
|
.alterId(0)
|
||||||
.email(tag + "@octopus.io")
|
.email(tag + "@octopus.io")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -123,46 +112,19 @@ public class XrayCoreServiceImpl implements XrayCoreService {
|
|||||||
pos
|
pos
|
||||||
);
|
);
|
||||||
|
|
||||||
// 持久化
|
// 持久化 Xray生成的文件信息
|
||||||
try {
|
XrayConfigInfo xrayConfigInfo = xrayConfigPersistor.persist(
|
||||||
String resultContent = objectMapper
|
xrayConfig,
|
||||||
.writerWithDefaultPrettyPrinter()
|
currentVersion,
|
||||||
.writeValueAsString(xrayConfig);
|
proxyNode
|
||||||
|
);
|
||||||
|
|
||||||
// 获得到文件名称
|
proxyNode.setXrayConfigInfo(xrayConfigInfo);
|
||||||
String timeString = TimeUtils.currentFormatTimeString();
|
|
||||||
String fileName = buildXrayConfigFileName(
|
|
||||||
proxyNode,
|
|
||||||
timeString
|
|
||||||
);
|
|
||||||
|
|
||||||
// 文件持久化!
|
|
||||||
File xrayConfigFile = xrayConfigPersistor.write(
|
|
||||||
fileName,
|
|
||||||
resultContent,
|
|
||||||
currentVersion
|
|
||||||
);
|
|
||||||
|
|
||||||
// 文件写入完成,保存文件信息
|
|
||||||
XrayConfigInfo xrayConfigInfo = new XrayConfigInfo();
|
|
||||||
xrayConfigInfo.setXrayConfigFile(xrayConfigFile);
|
|
||||||
xrayConfigInfo.setXrayConfigFileName(fileName);
|
|
||||||
|
|
||||||
proxyNode.setXrayConfigInfo(xrayConfigInfo);
|
|
||||||
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildXrayConfigFileName(ProxyNode proxyNode, String timeString) {
|
|
||||||
|
|
||||||
return proxyNode.getNum() + "-" + proxyNode.getAgentName() + "-" + timeString + ".json";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private XrayConfig doBuildXrayConfig(boolean isOutBoundFree, String tag, ClientObject clientObject, int port, ArrayList<ProxyNode> networkPathList, int pos) {
|
private XrayConfig doBuildXrayConfig(boolean isOutBoundFree, String tag, ClientObject clientObject, int port, ArrayList<ProxyNode> networkPathList, int pos) {
|
||||||
|
|||||||
Reference in New Issue
Block a user