fix: разделение правил маршрутизации секции (fix коллизии AND) и поддержка http/https ссылок
This commit is contained in:
@@ -2276,22 +2276,12 @@ function nft_populate_runtime_set_for_section(section, deferred_sections, table,
|
||||
"/tmp/sing-box/rulesets/community-subnets-" + service + ".lst",
|
||||
"/etc/tachyon/rulesets/community-subnets-" + service + ".lst"
|
||||
];
|
||||
let found = false;
|
||||
for (let path in cached_paths) {
|
||||
if (helpers.file_is_usable(path, 50)) {
|
||||
nft_add_file_chunks_to_family_sets(path, table, sets.subnets, sets.subnets6, "ips", "", "5000");
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (service == "discord") {
|
||||
nft_add_set_elements(table, sets.subnets, "162.158.0.0/15, 172.64.0.0/13, 138.128.136.0/21");
|
||||
}
|
||||
else if (service == "telegram") {
|
||||
nft_add_set_elements(table, sets.subnets, "149.154.160.0/20, 91.108.4.0/22, 91.108.8.0/22, 91.108.12.0/22, 91.108.16.0/22, 91.108.56.0/22, 5.28.192.0/18, 91.105.192.0/23, 95.161.64.0/20, 185.76.151.0/24, 194.221.0.0/16");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -643,8 +643,11 @@ function is_valid_detour(config, tag) {
|
||||
if (tag == runtime_constants.DIRECT_OUTBOUND_TAG || tag == runtime_constants.BYPASS_OUTBOUND_TAG)
|
||||
return true;
|
||||
for (let out in array_or_empty(config.outbounds)) {
|
||||
if (type(out) == "object" && out.tag == tag)
|
||||
if (type(out) == "object" && out.tag == tag) {
|
||||
if (out.tag == "DPI-out" || (out.type == "socks" && (out.server == "127.0.0.1" || out.server == "::1")))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1284,18 +1287,6 @@ function load_community_subnet_cidrs(community) {
|
||||
return cidrs;
|
||||
}
|
||||
}
|
||||
// Hardcoded seed fallback for cold boot before list-update downloads .lst
|
||||
if (service == "discord") {
|
||||
return [ "162.158.0.0/15", "172.64.0.0/13", "138.128.136.0/21" ];
|
||||
}
|
||||
if (service == "telegram") {
|
||||
return [
|
||||
"149.154.160.0/20", "91.108.4.0/22", "91.108.8.0/22",
|
||||
"91.108.12.0/22", "91.108.16.0/22", "91.108.56.0/22",
|
||||
"5.28.192.0/18", "91.105.192.0/23", "95.161.64.0/20",
|
||||
"185.76.151.0/24", "194.221.0.0/16"
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1321,10 +1312,8 @@ function add_combined_route_for_section(config, section) {
|
||||
let ensured = ensure_community_ruleset(config, section_name, service);
|
||||
push(rule_set_tags, ensured.tag);
|
||||
push(dns_rule_set_tags, ensured.tag);
|
||||
if (service != "cloudflare" && service != "cloudfront" && service != "hetzner" && service != "ovh" && service != "digitalocean") {
|
||||
for (let cidr in load_community_subnet_cidrs(community))
|
||||
push(ip_cidr, cidr);
|
||||
}
|
||||
for (let cidr in load_community_subnet_cidrs(community))
|
||||
push(ip_cidr, cidr);
|
||||
}
|
||||
for (let reference in connections.rule_sets(section)) {
|
||||
let ensured = ensure_custom_ruleset(config, as_string(reference));
|
||||
@@ -1355,9 +1344,9 @@ function add_combined_route_for_section(config, section) {
|
||||
if (target.unsupported)
|
||||
ctx.runtime_generate_unsupported(target.unsupported);
|
||||
|
||||
let has_domain_or_ruleset = length(domain) > 0 || length(domain_suffix) > 0 ||
|
||||
length(domain_keyword) > 0 || length(domain_regex) > 0 ||
|
||||
length(rule_set_tags) > 0;
|
||||
let has_domain = length(domain) > 0 || length(domain_suffix) > 0 ||
|
||||
length(domain_keyword) > 0 || length(domain_regex) > 0;
|
||||
let has_ruleset = length(rule_set_tags) > 0;
|
||||
let has_ip_cidr = length(ip_cidr) > 0;
|
||||
|
||||
let create_section_route_rule = function() {
|
||||
@@ -1375,14 +1364,12 @@ function add_combined_route_for_section(config, section) {
|
||||
return r;
|
||||
};
|
||||
|
||||
if (has_domain_or_ruleset) {
|
||||
if (has_domain) {
|
||||
let domain_rule = create_section_route_rule();
|
||||
add_domain_array(domain_rule, "domain", domain);
|
||||
add_domain_array(domain_rule, "domain_suffix", domain_suffix);
|
||||
add_domain_array(domain_rule, "domain_keyword", domain_keyword);
|
||||
add_domain_array(domain_rule, "domain_regex", domain_regex);
|
||||
if (length(rule_set_tags) > 0)
|
||||
domain_rule.rule_set = single_or_array(rule_set_tags);
|
||||
|
||||
let resolve = runtime_route.resolve_rule_for_section(section, domain_rule);
|
||||
if (type(resolve) == "object" && resolve.warning)
|
||||
@@ -1393,6 +1380,19 @@ function add_combined_route_for_section(config, section) {
|
||||
push_section_route_rule(config, domain_rule, target.outbound);
|
||||
}
|
||||
|
||||
if (has_ruleset) {
|
||||
let rs_rule = create_section_route_rule();
|
||||
rs_rule.rule_set = single_or_array(rule_set_tags);
|
||||
|
||||
let resolve = runtime_route.resolve_rule_for_section(section, rs_rule);
|
||||
if (type(resolve) == "object" && resolve.warning)
|
||||
warn(resolve.warning, "\n");
|
||||
else if (type(resolve) == "object" && resolve.rule)
|
||||
push(config.route.rules, resolve.rule);
|
||||
|
||||
push_section_route_rule(config, rs_rule, target.outbound);
|
||||
}
|
||||
|
||||
if (has_ip_cidr) {
|
||||
let ip_rule = create_section_route_rule();
|
||||
ip_rule.ip_cidr = ip_cidr;
|
||||
@@ -1426,7 +1426,7 @@ function add_combined_route_for_section(config, section) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_domain_or_ruleset && !has_ip_cidr && length(country_list) == 0) {
|
||||
if (!has_domain && !has_ruleset && !has_ip_cidr && length(country_list) == 0) {
|
||||
let fallback_rule = create_section_route_rule();
|
||||
let has_any_matcher = fallback_rule.source_ip_cidr != null ||
|
||||
fallback_rule.port != null || fallback_rule.port_range != null ||
|
||||
@@ -1629,20 +1629,20 @@ function add_service_route_rules(config, sections) {
|
||||
push(detour_domains, host);
|
||||
}
|
||||
if (length(detour_ips) > 0) {
|
||||
push(config.route.rules, {
|
||||
push_section_route_rule(config, {
|
||||
action: "route",
|
||||
inbound: tproxy_inbound_matcher(),
|
||||
outbound: detour_target,
|
||||
ip_cidr: single_or_array(detour_ips)
|
||||
});
|
||||
}, detour_target);
|
||||
}
|
||||
if (length(detour_domains) > 0) {
|
||||
push(config.route.rules, {
|
||||
push_section_route_rule(config, {
|
||||
action: "route",
|
||||
inbound: tproxy_inbound_matcher(),
|
||||
outbound: detour_target,
|
||||
domain: single_or_array(detour_domains)
|
||||
});
|
||||
}, detour_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ function is_supported_share_link(line) {
|
||||
starts_with(line, "socks://") ||
|
||||
starts_with(line, "socks4://") ||
|
||||
starts_with(line, "socks4a://") ||
|
||||
starts_with(line, "socks5://");
|
||||
starts_with(line, "socks5://") ||
|
||||
starts_with(line, "http://") ||
|
||||
starts_with(line, "https://");
|
||||
}
|
||||
|
||||
function split_csv(value) {
|
||||
@@ -880,6 +882,50 @@ function process_socks(raw, url) {
|
||||
return outbound;
|
||||
}
|
||||
|
||||
function process_http(raw, url) {
|
||||
let port = url.port;
|
||||
if (port == null || port == "")
|
||||
port = url.scheme == "https" ? 443 : 80;
|
||||
if (url.host == "" || is_dummy_server(url.host, port) || !valid_port(port))
|
||||
return null;
|
||||
|
||||
let username = "", password = "";
|
||||
if (url.userinfo != "") {
|
||||
let colon = index(url.userinfo, ":");
|
||||
if (colon >= 0) {
|
||||
username = urldecode(substr(url.userinfo, 0, colon));
|
||||
password = urldecode(substr(url.userinfo, colon + 1));
|
||||
if (username == password)
|
||||
password = "";
|
||||
}
|
||||
else {
|
||||
username = urldecode(url.userinfo);
|
||||
}
|
||||
}
|
||||
|
||||
let outbound = {
|
||||
type: "http",
|
||||
tag: url.fragment != "" ? url.fragment : (url.host + ":" + port),
|
||||
share_link: raw,
|
||||
server: url.host,
|
||||
server_port: int(port)
|
||||
};
|
||||
if (username != "")
|
||||
outbound.username = username;
|
||||
if (password != "")
|
||||
outbound.password = password;
|
||||
|
||||
if (url.scheme == "https") {
|
||||
let tls = { enabled: true };
|
||||
if ((url.query.sni || "") != "")
|
||||
tls.server_name = url.query.sni;
|
||||
if (is_true(url.query.allowInsecure || url.query.insecure))
|
||||
tls.insecure = true;
|
||||
outbound.tls = tls;
|
||||
}
|
||||
return outbound;
|
||||
}
|
||||
|
||||
function is_shadowsocks_userinfo_format(value) {
|
||||
if (type(value) != "string")
|
||||
return false;
|
||||
@@ -1183,6 +1229,8 @@ function parse_share_link(line) {
|
||||
return process_tuic(line, url);
|
||||
if (match(url.scheme, /^socks/))
|
||||
return process_socks(line, url);
|
||||
if (url.scheme == "http" || url.scheme == "https")
|
||||
return process_http(line, url);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +242,33 @@ function serialize_socks(outbound) {
|
||||
return scheme + "://" + auth + host_port(outbound.server, outbound.server_port) + fragment(outbound);
|
||||
}
|
||||
|
||||
function serialize_http(outbound) {
|
||||
if (as_string(outbound.server) == "" || outbound.server_port == null)
|
||||
return "";
|
||||
|
||||
let is_tls = type(outbound.tls) == "object" && (outbound.tls.enabled === true || outbound.tls.enabled == 1);
|
||||
let scheme = is_tls ? "https" : "http";
|
||||
let auth = "";
|
||||
if (as_string(outbound.username) != "") {
|
||||
auth = uri_encode(outbound.username);
|
||||
if (as_string(outbound.password) != "")
|
||||
auth += ":" + uri_encode(outbound.password);
|
||||
auth += "@";
|
||||
}
|
||||
|
||||
let params = [];
|
||||
if (is_tls && type(outbound.tls) == "object") {
|
||||
let tls = outbound.tls;
|
||||
if (tls.server_name)
|
||||
add_query(params, "sni", tls.server_name);
|
||||
if (tls.insecure === true)
|
||||
add_query(params, "insecure", "1");
|
||||
}
|
||||
|
||||
return scheme + "://" + auth + host_port(outbound.server, outbound.server_port) + query_string(params) + fragment(outbound);
|
||||
}
|
||||
|
||||
|
||||
function serialize_hysteria2(outbound) {
|
||||
let port = hysteria2_server_ports_uri(outbound);
|
||||
if (port == "" && outbound.server_port != null)
|
||||
@@ -365,6 +392,8 @@ function serialize_outbound_link(outbound) {
|
||||
return serialize_shadowsocks(outbound);
|
||||
if (outbound_type == "socks")
|
||||
return serialize_socks(outbound);
|
||||
if (outbound_type == "http")
|
||||
return serialize_http(outbound);
|
||||
if (outbound_type == "hysteria2")
|
||||
return serialize_hysteria2(outbound);
|
||||
if (outbound_type == "tuic")
|
||||
@@ -379,7 +408,8 @@ function is_copyable_link(value) {
|
||||
let prefixes = [
|
||||
"vless://", "vmess://", "trojan://", "ss://", "ssr://",
|
||||
"hysteria2://", "hy2://", "tuic://",
|
||||
"socks4://", "socks4a://", "socks5://"
|
||||
"socks4://", "socks4a://", "socks5://",
|
||||
"http://", "https://"
|
||||
];
|
||||
for (let prefix in prefixes) {
|
||||
if (starts_with(value, prefix))
|
||||
|
||||
Reference in New Issue
Block a user