feat: ASW-64 新增 api acl 接口

This commit is contained in:
shizhendong
2024-09-12 15:51:50 +08:00
parent 6bc0dcea4f
commit 139efeec0b
4 changed files with 231 additions and 2 deletions

View File

@@ -189,4 +189,61 @@ public class APIController {
Integer timeout = T.MapUtil.getInt(requestBody, "timeout", 10);
return R.ok().putData("result", adbUtil.execShellCommand(cmd, timeout));
}
@GetMapping("/acl")
public R listAcl() {
return R.ok().putData("records", adbUtil.listAcl());
}
@PostMapping("/acl")
public R addAcl(@RequestBody Map<String, Object> requestBody) {
String ip = T.MapUtil.getStr(requestBody, "ip");
String port = T.MapUtil.getStr(requestBody, "port");
if (T.StrUtil.isAllEmpty(ip, port)) {
return R.error(RCode.BAD_REQUEST);
}
String protocol = T.MapUtil.getStr(requestBody, "protocol", "all");
if (!T.StrUtil.equalsAny(protocol, "tcp", "udp", "all")) {
return R.error(RCode.BAD_REQUEST);
}
if ("all".equals(protocol) && T.StrUtil.isEmpty(ip)) {
return R.error(RCode.BAD_REQUEST);
}
adbUtil.addAcl(protocol, ip, port);
return R.ok().putData("records", adbUtil.listAcl());
}
@DeleteMapping("/acl")
public R deleteAcl(@RequestBody Map<String, Object> requestBody) {
String ip = T.MapUtil.getStr(requestBody, "ip");
String port = T.MapUtil.getStr(requestBody, "port");
if (T.StrUtil.isAllEmpty(ip, port)) {
return R.error(RCode.BAD_REQUEST);
}
String protocol = T.MapUtil.getStr(requestBody, "protocol", "all");
if (!T.StrUtil.equalsAny(protocol, "tcp", "udp", "all")) {
return R.error(RCode.BAD_REQUEST);
}
if ("all".equals(protocol) && T.StrUtil.isEmpty(ip)) {
return R.error(RCode.BAD_REQUEST);
}
adbUtil.deleteAcl(protocol, ip, port);
return R.ok().putData("records", adbUtil.listAcl());
}
@DeleteMapping("/acl/flush")
public R flushAcl() {
AdbUtil.CommandResult result = adbUtil.flushAcl();
if (0 != result.exitCode()) {
return R.error(result.output());
}
return R.ok();
}
}

View File

@@ -136,6 +136,68 @@ public class AdbCommandBuilder {
return this;
}
public AdbCommandBuilder buildIptablesLnRulesCommand(String chainName) {
this.command.add("shell");
this.command.add("iptables");
this.command.add("-nL");
this.command.add(chainName);
this.command.add("--line-numbers");
return this;
}
public AdbCommandBuilder buildIptablesAddRuleCommand(String chainName, String protocol, String ip, String port) {
this.command.add("shell");
this.command.add("iptables");
this.command.add("-A");
this.command.add(chainName);
this.command.add("-p");
this.command.add(protocol);
if (T.StrUtil.isNotEmpty(ip)) {
this.command.add("-d");
this.command.add(ip);
}
if (T.StrUtil.isNotEmpty(port) && !"all".equals(protocol)) {
this.command.add("--dport");
this.command.add(port);
}
this.command.add("-j");
this.command.add("ACCEPT");
return this;
}
public AdbCommandBuilder buildIptablesDelRuleCommand(String chainName, String protocol, String ip, String port) {
this.command.add("shell");
this.command.add("iptables");
this.command.add("-D");
this.command.add(chainName);
this.command.add("-p");
this.command.add(protocol);
if (T.StrUtil.isNotEmpty(ip)) {
this.command.add("-d");
this.command.add(ip);
}
if (T.StrUtil.isNotEmpty(port) && !"all".equals(protocol)) {
this.command.add("--dport");
this.command.add(port);
}
this.command.add("-j");
this.command.add("ACCEPT");
return this;
}
public AdbCommandBuilder buildIptablesFlushRuleCommand(String chainName) {
this.command.add("shell");
this.command.add("iptables");
this.command.add("-F");
this.command.add(chainName);
return this;
}
public List<String> build() {
return this.command;

View File

@@ -120,6 +120,9 @@ public class AdbUtil {
// 后台启动
this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_STOP --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0");
this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_START --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0");
// 添加自定义链
this.addAswOutputChain();
}
/**
@@ -703,6 +706,111 @@ public class AdbUtil {
}
}
/**
* 1. 添加自定义链
* 2. 自定义链添加到 OUTPUT 链中
*/
private void addAswOutputChain() {
// name=ASW_OUTPUT
this.execShellCommand("shell iptables -N ASW_OUTPUT");
String outputChainResult = CommandExec.exec(AdbCommandBuilder.builder()
.serial(this.getSerial())
.buildShellCommand(String.format("shell \"iptables -L OUTPUT --line-numbers | grep ASW_OUTPUT\""))
.build());
log.info("[addAswOutputChain] [ASW_OUTPUT in OUTPUT Chain] [result: {}]", outputChainResult);
if (T.StrUtil.isEmpty(outputChainResult)) {
// ASW_OUTPUT 添加到 OUTPUT 链中
this.execShellCommand("shell iptables -A OUTPUT -j ASW_OUTPUT");
}
}
/**
* ASW_OUTPUT chain rules
* iptables -nL ASW_OUTPUT --line-numbers
*/
public List<Map> listAcl() {
String result = CommandExec.exec(AdbCommandBuilder.builder()
.serial(this.getSerial())
.buildIptablesLnRulesCommand("ASW_OUTPUT")
.build());
List<Map> chainList = T.ListUtil.list(true);
String[] lines = result.split("\\n");
for (String line : lines) {
String[] split = line.split("\\s+");
String chainIndex = T.StrUtil.trim(split[0]);
if (T.StrUtil.isNumeric(chainIndex)) {
String protocol = T.StrUtil.trim(split[2]);
Map<Object, Object> m = T.MapUtil.builder()
.put("num", Integer.valueOf(chainIndex))
.put("protocol", protocol)
.build();
String destIp = T.StrUtil.trim(split[5]);
if (!T.StrUtil.equals("0.0.0.0/0", destIp)) {
m.put("ip", destIp);
}
if (split.length == 8) {
String dpt = T.StrUtil.trim(split[7]);
dpt = dpt.replaceAll("dpt:", "");
if (T.StrUtil.isNumeric(chainIndex)) {
m.put("port", Integer.valueOf(dpt));
}
}
chainList.add(m);
}
}
return chainList;
}
/**
* add chain rule
* iptables -A ASW_OUTPUT -p prot -d ip --dport port -j ACCEPT
*/
public void addAcl(String protocol, String ip, String port) {
// add chain
this.addAswOutputChain();
// add chain ruls
String result = CommandExec.exec(AdbCommandBuilder.builder()
.serial(this.getSerial())
.buildIptablesAddRuleCommand("ASW_OUTPUT", protocol, ip, port)
.build());
log.info("[addAcl] [protocol: {}] [ip: {}] [port: {}] [result: {}]", protocol, ip, port, result);
}
/**
* del chain rule
* iptables -D ASW_OUTPUT -p prot -d ip --dport port -j ACCEPT
*/
public void deleteAcl(String protocol, String ip, String port) {
// add chain ruls
String result = CommandExec.exec(AdbCommandBuilder.builder()
.serial(this.getSerial())
.buildIptablesDelRuleCommand("ASW_OUTPUT", protocol, ip, port)
.build());
log.info("[deleteAcl] [protocol: {}] [ip: {}] [port: {}] [result: {}]", protocol, ip, port, result);
}
/**
* flushAcl
* iptables -F ASW_OUTPUT
*/
public CommandResult flushAcl() {
String result = CommandExec.exec(AdbCommandBuilder.builder()
.serial(this.getSerial())
.buildIptablesFlushRuleCommand("ASW_OUTPUT")
.build());
log.info("[flushAcl] [result: {}]", result);
return new CommandResult(T.StrUtil.isNotEmpty(result) ? 1 : 0, result);
}
private synchronized ExecutorService getThreadPool() {
if (threadPool == null) {
threadPool = new ThreadPoolExecutor(

View File

@@ -11,7 +11,9 @@ public class Constant {
static {
File tempPath = T.FileUtil.file(TEMP_PATH);
// 程序启动清空临时目录
T.FileUtil.del(tempPath);
// T.FileUtil.del(tempPath);
if (!T.FileUtil.exist(tempPath)) {
T.FileUtil.mkdir(tempPath);
}
}
}