Преглед изворни кода

解决启动退出ssh问题

Gogs пре 6 дана
родитељ
комит
a004bd9cdf
6 измењених фајлова са 119 додато и 42 уклоњено
  1. 6 0
      README.md
  2. BIN
      __pycache__/cli.cpython-313.pyc
  3. 86 41
      cli.py
  4. 3 1
      config.json
  5. 12 0
      config.jsonbak
  6. 12 0
      scripts/start-transparent.sh

+ 6 - 0
README.md

@@ -98,6 +98,12 @@ cp /home/mynetspeeder/demo-config.json /home/mynetspeeder/config.json
 sudo /home/mynetspeeder/scripts/start-transparent.sh --capture-uid <sing-box运行UID> /home/mynetspeeder/config.json
 ```
 
+不指定 `--capture-uid` 时,默认接管所有用户发起的流量:
+
+```bash
+sudo /home/mynetspeeder/scripts/start-transparent.sh /home/mynetspeeder/config.json
+```
+
 停止透明接管:
 
 ```bash

BIN
__pycache__/cli.cpython-313.pyc


+ 86 - 41
cli.py

@@ -14,9 +14,12 @@ from .relay_client import RelayManager
 from .transparent_edge import TransparentEdge
 
 
-WIN_RE = re.compile(
+TCP_WIN_RE = re.compile(
     r"tcp win session=(?P<session>\d+) target=(?P<host>[^:]+):(?P<port>\d+) winner=(?P<winner>\S+) .*?direct=(?P<direct>\d+) .*?relay=(?P<relay>\d+)"
 )
+UDP_WIN_RE = re.compile(
+    r"udp flow=(?P<flow>\d+) winner=(?P<winner>\S+) target=(?P<host>[^:]+):(?P<port>\d+)"
+)
 
 
 def build_parser() -> argparse.ArgumentParser:
@@ -79,47 +82,87 @@ def handle_summary(args: argparse.Namespace) -> int:
     if not log_path.exists():
         raise SystemExit(f"log file not found: {log_path}")
 
-    total = 0
-    direct = 0
-    relay = 0
-    winners: dict[str, int] = defaultdict(int)
-    targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
+    tcp_total = 0
+    tcp_direct = 0
+    tcp_relay = 0
+    tcp_winners: dict[str, int] = defaultdict(int)
+    tcp_targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
+
+    udp_total = 0
+    udp_direct = 0
+    udp_relay = 0
+    udp_winners: dict[str, int] = defaultdict(int)
+    udp_targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
 
     for line in log_path.read_text(errors="replace").splitlines():
-        match = WIN_RE.search(line)
-        if not match:
+        tcp_match = TCP_WIN_RE.search(line)
+        if tcp_match:
+            tcp_total += 1
+            winner = tcp_match.group("winner")
+            host = tcp_match.group("host")
+            port = tcp_match.group("port")
+            key = f"{host}:{port}"
+            tcp_winners[winner] += 1
+            tcp_targets[key][winner] += 1
+            if winner == "direct":
+                tcp_direct += 1
+            else:
+                tcp_relay += 1
             continue
-        total += 1
-        winner = match.group("winner")
-        host = match.group("host")
-        port = match.group("port")
-        key = f"{host}:{port}"
-        winners[winner] += 1
-        targets[key][winner] += 1
-        if winner == "direct":
-            direct += 1
-        else:
-            relay += 1
-
-    ordered_targets = sorted(
-        targets.items(),
+
+        udp_match = UDP_WIN_RE.search(line)
+        if udp_match:
+            udp_total += 1
+            winner = udp_match.group("winner")
+            host = udp_match.group("host")
+            port = udp_match.group("port")
+            key = f"{host}:{port}"
+            udp_winners[winner] += 1
+            udp_targets[key][winner] += 1
+            if winner == "direct":
+                udp_direct += 1
+            else:
+                udp_relay += 1
+
+    tcp_ordered_targets = sorted(
+        tcp_targets.items(),
+        key=lambda item: sum(item[1].values()),
+        reverse=True,
+    )[: max(args.top, 0)]
+    udp_ordered_targets = sorted(
+        udp_targets.items(),
         key=lambda item: sum(item[1].values()),
         reverse=True,
     )[: max(args.top, 0)]
 
     result = {
         "log_file": str(log_path),
-        "total": total,
-        "direct": direct,
-        "relay": relay,
-        "winners": dict(sorted(winners.items(), key=lambda item: (-item[1], item[0]))),
-        "targets": [
-            {
-                "target": target,
-                "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
-            }
-            for target, counts in ordered_targets
-        ],
+        "tcp": {
+            "total": tcp_total,
+            "direct": tcp_direct,
+            "relay": tcp_relay,
+            "winners": dict(sorted(tcp_winners.items(), key=lambda item: (-item[1], item[0]))),
+            "targets": [
+                {
+                    "target": target,
+                    "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
+                }
+                for target, counts in tcp_ordered_targets
+            ],
+        },
+        "udp": {
+            "total": udp_total,
+            "direct": udp_direct,
+            "relay": udp_relay,
+            "winners": dict(sorted(udp_winners.items(), key=lambda item: (-item[1], item[0]))),
+            "targets": [
+                {
+                    "target": target,
+                    "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
+                }
+                for target, counts in udp_ordered_targets
+            ],
+        },
     }
 
     if args.json:
@@ -127,14 +170,16 @@ def handle_summary(args: argparse.Namespace) -> int:
         return 0
 
     print(f"log: {log_path}")
-    print(f"total: {total} direct: {direct} relay: {relay}")
-    print("winners:")
-    for name, count in result["winners"].items():
-        print(f"  {name}: {count}")
-    print("targets:")
-    for item in result["targets"]:
-        wins = ", ".join(f"{name}={count}" for name, count in item["wins"].items())
-        print(f"  {item['target']}: {wins}")
+    for protocol in ("tcp", "udp"):
+        section = result[protocol]
+        print(f"{protocol}: total={section['total']} direct={section['direct']} relay={section['relay']}")
+        print("winners:")
+        for name, count in section["winners"].items():
+            print(f"  {name}: {count}")
+        print("targets:")
+        for item in section["targets"]:
+            wins = ", ".join(f"{name}={count}" for name, count in item["wins"].items())
+            print(f"  {item['target']}: {wins}")
     return 0
 
 

+ 3 - 1
config.json

@@ -4,5 +4,7 @@
   "tcp_warmup_bytes": 1048576,
   "tcp_loser_grace_ms": 1500,
   "probe_interval": 3,
-  "relays": [{"name": "hk1", "host": "141.140.15.30", "port": 9009, "token": "130", "weight": 100}]
+  "relays": [
+  ]
+  
 }

+ 12 - 0
config.jsonbak

@@ -0,0 +1,12 @@
+{
+  "strategy": "top3",
+  "redundancy": 3,
+  "tcp_warmup_bytes": 1048576,
+  "tcp_loser_grace_ms": 1500,
+  "probe_interval": 3,
+  "relays": [
+    {"name": "hk1", "host": "141.140.15.30", "port": 9009, "token": "130", "weight": 100},
+    {"name": "hk2", "host": "23.95.134.159", "port": 9009, "token": "130", "weight": 100}
+  ]
+  
+}

+ 12 - 0
scripts/start-transparent.sh

@@ -44,11 +44,17 @@ LOG_MAX_MB="${MYNETSPEEDER_LOG_MAX_MB:-50}"
 LOG_BACKUPS="${MYNETSPEEDER_LOG_BACKUPS:-3}"
 CHAIN4="MYNETSPEEDER"
 CHAIN6="MYNETSPEEDER6"
+SSH_PORTS="${MYNETSPEEDER_SSH_PORTS:-22}"
 
 if [[ $EUID -ne 0 ]]; then echo "need root"; exit 1; fi
 if [[ ! -f "$CONFIG_PATH" ]]; then echo "config not found: $CONFIG_PATH"; exit 1; fi
 if [[ -n "$CAPTURE_UID" ]] && ! [[ "$CAPTURE_UID" =~ ^[0-9]+$ ]]; then echo "capture uid must be numeric"; exit 1; fi
 
+IFS=',' read -r -a SSH_PORT_ARRAY <<< "$SSH_PORTS"
+for ssh_port in "${SSH_PORT_ARRAY[@]}"; do
+  [[ "$ssh_port" =~ ^[0-9]+$ ]] || { echo "ssh ports must be numeric, got: $ssh_port"; exit 1; }
+done
+
 id -u "$RUNTIME_USER" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$RUNTIME_USER"
 mkdir -p /var/log
 touch "$LOG_FILE"
@@ -71,6 +77,9 @@ iptables -t nat -N "$CHAIN4" 2>/dev/null || true
 iptables -t nat -F "$CHAIN4"
 iptables -t nat -A "$CHAIN4" -d 127.0.0.0/8 -j RETURN
 iptables -t nat -A "$CHAIN4" -m owner --uid-owner "$RUNTIME_USER" -j RETURN
+for ssh_port in "${SSH_PORT_ARRAY[@]}"; do
+  iptables -t nat -A "$CHAIN4" -p tcp --sport "$ssh_port" -j RETURN
+done
 while read -r host; do
   [[ -n "$host" && "$host" != *:* ]] && iptables -t nat -A "$CHAIN4" -d "$host" -j RETURN
 done < <(python3 - <<'PY' "$CONFIG_PATH"
@@ -100,6 +109,9 @@ if command -v ip6tables >/dev/null 2>&1; then
   ip6tables -t nat -F "$CHAIN6"
   ip6tables -t nat -A "$CHAIN6" -d ::1/128 -j RETURN
   ip6tables -t nat -A "$CHAIN6" -m owner --uid-owner "$RUNTIME_USER" -j RETURN
+  for ssh_port in "${SSH_PORT_ARRAY[@]}"; do
+    ip6tables -t nat -A "$CHAIN6" -p tcp --sport "$ssh_port" -j RETURN
+  done
   while read -r host; do
     [[ -n "$host" && "$host" == *:* ]] && ip6tables -t nat -A "$CHAIN6" -d "$host" -j RETURN
   done < <(python3 - <<'PY' "$CONFIG_PATH"