feat(p2p): поле портов торрент-клиента для изоляции P2P (issue #31)

This commit is contained in:
Dushnilin
2026-08-14 09:46:15 +03:00
parent 7bd373c392
commit 65b216b6a2
10 changed files with 174 additions and 1 deletions
+56 -1
View File
@@ -15,6 +15,58 @@ function bool_value(value) {
return value === true || value == "1" || value == "true" || value == "yes" || value == "on";
}
function normalize_port_entry(value) {
value = trim(as_string(value));
if (value == "" || match(value, /^[0-9]+$/) == null)
return null;
let number = int(value);
return number >= 1 && number <= 65535 ? number : null;
}
// P2P leak protection can be pinned down to the torrent client's own ports so
// nothing sneaks past the protocol sniffer. Each entry is "proto" or
// "proto:port" or "proto:port-port" (tcp/udp, comma separated). Without a
// port the whole protocol is routed direct.
function p2p_direct_rules(settings) {
let rules = [];
for (let entry in split(option(settings, "p2p_ports", ""), ",")) {
entry = trim(entry);
if (entry == "")
continue;
let proto = "tcp";
let port_spec = "";
let colon = index(entry, ":");
if (colon >= 0) {
proto = trim(substr(entry, 0, colon));
port_spec = trim(substr(entry, colon + 1));
} else {
proto = entry;
}
if (proto != "tcp" && proto != "udp")
continue;
let rule = { protocol: [ proto ], action: "route", outbound: runtime_constants.DIRECT_OUTBOUND_TAG };
if (port_spec != "") {
let dash = index(port_spec, "-");
if (dash >= 0) {
let start = normalize_port_entry(substr(port_spec, 0, dash));
let end = normalize_port_entry(substr(port_spec, dash + 1));
if (start != null && end != null && start <= end)
rule.source_port_range = [ sprintf("%d:%d", start, end) ];
else
continue;
} else {
let port = normalize_port_entry(port_spec);
if (port != null)
rule.source_port = port;
else
continue;
}
}
push(rules, rule);
}
return rules;
}
function config(settings, runtime) {
let output_network_interface = option(settings, "output_network_interface", "");
let mwan3_active = type(runtime) == "object" && bool_value(runtime.mwan3_active);
@@ -41,8 +93,11 @@ function config(settings, runtime) {
result.default_interface = output_network_interface;
if (bool_option(settings, "disable_quic", false))
push(result.rules, { action: "reject", inbound: runtime_constants.TPROXY_INBOUND_TAG, protocol: "quic" });
if (bool_option(settings, "isolate_p2p", false))
if (bool_option(settings, "isolate_p2p", false)) {
push(result.rules, { protocol: "bittorrent", action: "route", outbound: runtime_constants.DIRECT_OUTBOUND_TAG });
for (let rule in p2p_direct_rules(settings))
push(result.rules, rule);
}
return result;
}