op-packages/luci-app-xray/root/usr/share/xray/firewall_include.ut
github-actions[bot] 9a2ef6ebbc 🎁 Sync 2026-05-19 21:08:14
2026-05-19 21:08:15 +08:00

637 lines
27 KiB
Plaintext

#!/usr/bin/utpl
{%
"use strict";
import { stat } from "fs";
import { load_config } from "./common/config.mjs";
import { dns_direct_servers } from "./feature/dns.mjs";
const ignore_tp_spec_def_gw = stat("/usr/share/xray/ignore_tp_spec_def_gw");
const config = load_config();
const general = config[filter(keys(config), k => config[k][".type"] == "general")[0]];
const general_mark = general.mark || 255;
const tcp4_enabled = length(general.tcp_balancer_v4 || []) > 0;
const udp4_enabled = length(general.udp_balancer_v4 || []) > 0;
const tcp6_enabled = length(general.tcp_balancer_v6 || []) > 0;
const udp6_enabled = length(general.udp_balancer_v6 || []) > 0;
const uids_direct = uniq(general.uids_direct || []);
const gids_direct = uniq(general.gids_direct || []);
let wan_bp_ips = uniq(general.wan_bp_ips || []);
let wan_fw_ips = uniq(general.wan_fw_ips || []);
let wan_bp_dns = dns_direct_servers(config);
const wan_bp_ips_v4 = filter(wan_bp_ips, v => index(v, ":") == -1);
const wan_bp_ips_v6 = filter(wan_bp_ips, v => index(v, ":") != -1);
const wan_fw_ips_v4 = filter(wan_fw_ips, v => index(v, ":") == -1);
const wan_fw_ips_v6 = filter(wan_fw_ips, v => index(v, ":") != -1);
const wan_bp_dns_v4 = filter(wan_bp_dns, v => index(v.ip, ":") == -1);
const wan_bp_dns_v6 = filter(wan_bp_dns, v => index(v.ip, ":") != -1);
const transparent_default_port_policy = general.transparent_default_port_policy || "forwarded";
const wan_fw_tcp_ports = general.wan_fw_tcp_ports || [];
const wan_fw_udp_ports = general.wan_fw_udp_ports || [];
const wan_bp_tcp_ports = general.wan_bp_tcp_ports || [];
const wan_bp_udp_ports = general.wan_bp_udp_ports || [];
const counter = function () {
if (general.fw4_counter == "1") {
return "counter packets 0 bytes 0";
}
return "";
}();
const firewall_priority = function () {
if (general.firewall_priority == null) {
return "+10";
}
if (int(general.firewall_priority) > 0) {
return sprintf("+%s", general.firewall_priority);
};
return sprintf("%s", general.firewall_priority);
}();
const fakedns = map(filter(keys(config), k => config[k][".type"] == "fakedns") || [], k => config[k]);
const manual_tproxy = filter(keys(config), k => config[k][".type"] == "manual_tproxy") || [];
const manual_tproxy_source_ips = filter(map(manual_tproxy, k => config[k]["source_addr"]) || [], v => index(v, ":") == -1);
const tp_spec_sm4_tp = uniq(map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v4 == "tproxy"), k => config[k].macaddr) || []);
const tp_spec_sm6_tp = uniq(map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v6 == "tproxy"), k => config[k].macaddr) || []);
const tp_spec_sm4_bp = uniq(map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v4 == "bypass"), k => config[k].macaddr) || []);
const tp_spec_sm6_bp = uniq(map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v6 == "bypass"), k => config[k].macaddr) || []);
const tp_spec_sm4_fw = map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v4 == "forward"), k => config[k]);
const tp_spec_sm6_fw = map(filter(keys(config), k => config[k][".type"] == "lan_hosts" && config[k].access_control_strategy_v6 == "forward"), k => config[k]);
const used_extra_inbound = uniq([
...map(tp_spec_sm4_fw, k => k["access_control_forward_tcp_v4"]),
...map(tp_spec_sm4_fw, k => k["access_control_forward_udp_v4"]),
...map(tp_spec_sm6_fw, k => k["access_control_forward_tcp_v6"]),
...map(tp_spec_sm6_fw, k => k["access_control_forward_udp_v6"]),
]);
let extra_inbound_tcp_v4_map = {};
let extra_inbound_udp_v4_map = {};
let extra_inbound_tcp_v6_map = {};
let extra_inbound_udp_v6_map = {};
for (let i in used_extra_inbound) {
let tcp_v4_items = [];
let udp_v4_items = [];
let tcp_v6_items = [];
let udp_v6_items = [];
for (let j in tp_spec_sm4_fw) {
if (j["access_control_forward_tcp_v4"] == i) {
push(tcp_v4_items, j["macaddr"]);
}
if (j["access_control_forward_udp_v4"] == i) {
push(udp_v4_items, j["macaddr"]);
}
}
if (length(tcp_v4_items) > 0) {
extra_inbound_tcp_v4_map[i] = tcp_v4_items;
}
if (length(udp_v4_items) > 0) {
extra_inbound_udp_v4_map[i] = udp_v4_items;
}
for (let j in tp_spec_sm6_fw) {
if (j["access_control_forward_tcp_v6"] == i) {
push(tcp_v6_items, j["macaddr"]);
}
if (j["access_control_forward_udp_v6"] == i) {
push(udp_v6_items, j["macaddr"]);
}
}
if (length(tcp_v6_items) > 0) {
extra_inbound_tcp_v6_map[i] = tcp_v6_items;
}
if (length(udp_v6_items) > 0) {
extra_inbound_udp_v6_map[i] = udp_v6_items;
}
}
const ttl_override = int(general.ttl_override);
const hop_limit_override = int(general.hop_limit_override);
const ttl_hop_limit_match = int(general.ttl_hop_limit_match);
const dynamic_direct_timeout = general.dynamic_direct_timeout || 2233;
const dynamic_direct_tcp4 = function () {
if (general.dynamic_direct_tcp4 == "1") {
return `update @tp_spec_dv4_dd { ip daddr timeout ${dynamic_direct_timeout}s } update @tp_spec_dv4_dd { ip saddr timeout ${dynamic_direct_timeout}s }`;
}
return "";
}();
const dynamic_direct_tcp6 = function () {
if (general.dynamic_direct_tcp6 == "1") {
return `update @tp_spec_dv6_dd { ip6 daddr timeout ${dynamic_direct_timeout}s } update @tp_spec_dv6_dd { ip6 saddr timeout ${dynamic_direct_timeout}s }`;
}
return "";
}();
const dynamic_direct_udp4 = function () {
if (general.dynamic_direct_udp4 == "1") {
return `update @tp_spec_dv4_dd { ip daddr timeout ${dynamic_direct_timeout}s } update @tp_spec_dv4_dd { ip saddr timeout ${dynamic_direct_timeout}s }`;
}
return "";
}();
const dynamic_direct_udp6 = function () {
if (general.dynamic_direct_udp6 == "1") {
return `update @tp_spec_dv6_dd { ip6 daddr timeout ${dynamic_direct_timeout}s } update @tp_spec_dv6_dd { ip6 saddr timeout ${dynamic_direct_timeout}s }`;
}
return "";
}();
const dynamic_direct_conntrack_tcp = function () {
if (general.dynamic_direct_tcp4 == "1" || general.dynamic_direct_tcp6 == "1") {
return "update @tp_spec_ctt_dd { meta nfproto . tcp sport timeout 30s }";
}
return "";
}();
const dynamic_direct_conntrack_udp = function () {
if (general.dynamic_direct_udp4 == "1" || general.dynamic_direct_udp6 == "1") {
return "update @tp_spec_ctu_dd { meta nfproto . udp sport timeout 30s }";
}
return "";
}();
%}
{% if (length(wan_bp_dns_v4) > 0): %}
set tp_spec_dp4_bp {
typeof ip daddr . udp dport
size {{ length(wan_bp_dns_v4) * 2 + 1 }}
flags interval
elements = {
{{ join(", ", uniq(map(wan_bp_dns_v4, v => `${v.ip} . ${v.port}`))) }}
}
}
{% endif %}
{% if (length(wan_bp_dns_v6) > 0): %}
set tp_spec_dp6_bp {
typeof ip6 daddr . udp dport
size {{ length(wan_bp_dns_v6) * 2 + 1 }}
flags interval
elements = {
{{ join(", ", uniq(map(wan_bp_dns_v6, v => `${v.ip} . ${v.port}`))) }}
}
}
{% endif %}
set tp_spec_dv4_sp {
type ipv4_addr
size 32
flags interval
elements = { 0.0.0.0/8, 10.0.0.0/8,
100.64.0.0/10, 127.0.0.0/8,
169.254.0.0/16, 172.16.0.0/12,
192.0.0.0/24, 192.52.193.0/24,
192.168.0.0/16, 224.0.0.0/3 }
}
set tp_spec_dv6_sp {
type ipv6_addr
size 32
flags interval
elements = { ::,
::1,
::ffff:0.0.0.0/96,
::ffff:0:0:0/96,
64:ff9b::/96,
100::/64,
2001::/32,
2001:20::/28,
2001:db8::/32,
2002::/16,
fc00::/7,
fe80::/10,
ff00::/8 }
}
{% if (length(tp_spec_sm4_bp) > 0): %}
set tp_spec_sm4_bp {
type ether_addr
size {{ length(tp_spec_sm4_bp) * 2 + 1 }}
elements = { {{ join(", ", tp_spec_sm4_bp) }} }
}
{% endif %}
{% if (length(tp_spec_sm6_bp) > 0): %}
set tp_spec_sm6_bp {
type ether_addr
size {{ length(tp_spec_sm6_bp) * 2 + 1 }}
elements = { {{ join(", ", tp_spec_sm6_bp) }} }
}
{% endif %}
{% if (length(tp_spec_sm4_tp) > 0): %}
set tp_spec_sm4_tp {
type ether_addr
size {{ length(tp_spec_sm4_tp) * 2 + 1 }}
elements = { {{ join(", ", tp_spec_sm4_tp) }} }
}
{% endif %}
{% if (length(tp_spec_sm6_tp) > 0): %}
set tp_spec_sm6_tp {
type ether_addr
size {{ length(tp_spec_sm6_tp) * 2 + 1 }}
elements = { {{ join(", ", tp_spec_sm6_tp) }} }
}
{% endif %}
{% for (let i in extra_inbound_tcp_v4_map): %}
set tp_spec_sm4_ft_{{ i }} {
type ether_addr
size {{ length(extra_inbound_tcp_v4_map) * 2 + 1 }}
elements = { {{ join(", ", extra_inbound_tcp_v4_map[i]) }} }
}
{% endfor %}
{% for (let i in extra_inbound_udp_v4_map): %}
set tp_spec_sm4_fu_{{ i }} {
type ether_addr
size {{ length(extra_inbound_udp_v4_map) * 2 + 1 }}
elements = { {{ join(", ", extra_inbound_udp_v4_map[i]) }} }
}
{% endfor %}
{% for (let i in extra_inbound_tcp_v6_map): %}
set tp_spec_sm6_ft_{{ i }} {
type ether_addr
size {{ length(extra_inbound_tcp_v6_map) * 2 + 1 }}
elements = { {{ join(", ", extra_inbound_tcp_v6_map[i]) }} }
}
{% endfor %}
{% for (let i in extra_inbound_udp_v6_map): %}
set tp_spec_sm6_fu_{{ i }} {
type ether_addr
size {{ length(extra_inbound_udp_v6_map) * 2 + 1 }}
elements = { {{ join(", ", extra_inbound_udp_v6_map[i]) }} }
}
{% endfor %}
{% if (length(manual_tproxy_source_ips) > 0): %}
set tp_spec_dv4_mt {
type ipv4_addr
size {{ length(manual_tproxy_source_ips) * 2 + 1 }}
elements = { {{ join(", ", manual_tproxy_source_ips) }} }
}
{% endif %}
{% if (length(wan_bp_ips_v4) > 0): %}
set tp_spec_dv4_bp {
type ipv4_addr
size {{ length(wan_bp_ips_v4) * 2 + 1 }}
flags interval
elements = { {{ join(", ", wan_bp_ips_v4)}} }
}
{% endif %}
{% if (length(wan_bp_ips_v6) > 0): %}
set tp_spec_dv6_bp {
type ipv6_addr
size {{ length(wan_bp_ips_v6) * 2 + 1 }}
flags interval
elements = { {{ join(", ", wan_bp_ips_v6)}} }
}
{% endif %}
{% if (length(wan_fw_ips_v4) > 0): %}
set tp_spec_dv4_fw {
type ipv4_addr
size {{ length(wan_fw_ips_v4) * 2 + 1 }}
flags interval
elements = { {{ join(", ", wan_fw_ips_v4)}} }
}
{% endif %}
{% if (length(wan_fw_ips_v6) > 0): %}
set tp_spec_dv6_fw {
type ipv6_addr
size {{ length(wan_fw_ips_v6) * 2 + 1 }}
flags interval
elements = { {{ join(", ", wan_fw_ips_v6)}} }
}
{% endif %}
{% if (ignore_tp_spec_def_gw == null): %}
set tp_spec_dv4_dg {
type ipv4_addr
size 16
flags interval
}
{% endif %}
set tp_spec_dv6_dg {
type ipv6_addr
size 16
flags interval
}
{% if (general.dynamic_direct_tcp4 == "1" || general.dynamic_direct_udp4 == "1"): %}
set tp_spec_dv4_dd {
type ipv4_addr
size 65536
flags timeout
}
{% endif %}
{% if (general.dynamic_direct_tcp6 == "1" || general.dynamic_direct_udp6 == "1"): %}
set tp_spec_dv6_dd {
type ipv6_addr
size 65536
flags timeout
}
{% endif %}
{% if (dynamic_direct_conntrack_tcp != ""): %}
set tp_spec_ctt_dd {
typeof meta nfproto . tcp sport
size 65536
flags timeout
}
{% endif %}
{% if (dynamic_direct_conntrack_udp != ""): %}
set tp_spec_ctu_dd {
typeof meta nfproto . udp sport
size 65536
flags timeout
}
{% endif %}
chain xray_transparent_proxy {
type filter hook prerouting priority filter {{ firewall_priority }}; policy accept;
mark 0x000000fb {{ counter }} goto tp_spec_wan_fw
ip protocol tcp {{ counter }} accept
ip protocol udp {{ counter }} accept
ip6 nexthdr tcp {{ counter }} accept
ip6 nexthdr udp {{ counter }} accept
{{ counter }} accept
}
chain tp_spec_wan_fw {
{% if (length(fakedns) > 0): %}
ip protocol tcp ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} {{ counter }} tproxy ip to :{{ general.tproxy_port_tcp_f4 || 1086 }} accept
ip protocol udp ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} {{ counter }} tproxy ip to :{{ general.tproxy_port_udp_f4 || 1088 }} accept
ip6 nexthdr tcp ip6 daddr {{ general.pool_v6 || "fc00::/18" }} {{ counter }} tproxy ip6 to :{{ general.tproxy_port_tcp_f6 || 1087 }} accept
ip6 nexthdr udp ip6 daddr {{ general.pool_v6 || "fc00::/18" }} {{ counter }} tproxy ip6 to :{{ general.tproxy_port_udp_f6 || 1089 }} accept
{% endif %}
{% if (length(manual_tproxy_source_ips) > 0): %}
ip protocol tcp ip daddr @tp_spec_dv4_mt {{ counter }} tproxy ip to :{{ general.tproxy_port_tcp_v4 || 1082 }} accept
ip protocol udp ip daddr @tp_spec_dv4_mt {{ counter }} tproxy ip to :{{ general.tproxy_port_udp_v4 || 1084 }} accept
{% endif %}
{% for (let i in extra_inbound_tcp_v4_map): %}
ip protocol tcp ether saddr @tp_spec_sm4_ft_{{ i }} {{ counter }} tproxy ip to :{{ config[i].inbound_port }} accept
{% endfor %}
{% for (let i in extra_inbound_udp_v4_map): %}
ip protocol udp ether saddr @tp_spec_sm4_fu_{{ i }} {{ counter }} tproxy ip to :{{ config[i].inbound_port }} accept
{% endfor %}
{% for (let i in extra_inbound_tcp_v6_map): %}
ip6 nexthdr tcp ether saddr @tp_spec_sm6_ft_{{ i }} {{ counter }} tproxy ip6 to :{{ config[i].inbound_port }} accept
{% endfor %}
{% for (let i in extra_inbound_udp_v6_map): %}
ip6 nexthdr udp ether saddr @tp_spec_sm6_fu_{{ i }} {{ counter }} tproxy ip6 to :{{ config[i].inbound_port }} accept
{% endfor %}
{% if (tcp4_enabled): %}
ip protocol tcp {{ counter }} tproxy ip to :{{ general.tproxy_port_tcp_v4 || 1082 }} accept
{% else %}
ip protocol tcp {{ counter }} meta mark set {{ sprintf("0x%08x", general_mark) }} accept
{% endif %}
{% if (udp4_enabled): %}
ip protocol udp {{ counter }} tproxy ip to :{{ general.tproxy_port_udp_v4 || 1084 }} accept
{% else %}
ip protocol udp {{ counter }} meta mark set {{ sprintf("0x%08x", general_mark) }} accept
{% endif %}
{% if (tcp6_enabled): %}
ip6 nexthdr tcp {{ counter }} tproxy ip6 to :{{ general.tproxy_port_tcp_v6 || 1083 }} accept
{% else %}
ip6 nexthdr tcp {{ counter }} meta mark set {{ sprintf("0x%08x", general_mark) }} accept
{% endif %}
{% if (udp6_enabled): %}
ip6 nexthdr udp {{ counter }} tproxy ip6 to :{{ general.tproxy_port_udp_v6 || 1085 }} accept
{% else %}
ip6 nexthdr udp {{ counter }} meta mark set {{ sprintf("0x%08x", general_mark) }} accept
{% endif %}
{{ counter }} accept
}
chain xray_prerouting {
type filter hook prerouting priority mangle {{ firewall_priority }}; policy accept;
{% if (length(general.ttl_override_bypass_ports) > 0): %}
tcp dport { {{ join(', ', general.ttl_override_bypass_ports) }} } {{ counter }} meta l4proto tcp accept
udp dport { {{ join(', ', general.ttl_override_bypass_ports) }} } {{ counter }} meta l4proto udp accept
{% endif %}
{% if (ttl_override > 0): %}
ip ttl {{ ttl_hop_limit_match }} {{ counter }} ip ttl set {{ ttl_override }}
{% endif %}
{% if (hop_limit_override > 0): %}
ip6 hoplimit {{ ttl_hop_limit_match }} {{ counter }} ip6 hoplimit set {{ hop_limit_override }}
{% endif %}
{% if (general.dynamic_direct_tcp4 == "1"): %}
ip protocol tcp ct mark 0x000000fa {{ counter }} {{ dynamic_direct_tcp4 }} accept comment "Xray dynamic direct TCP4"
{% endif %}
{% if (general.dynamic_direct_udp4 == "1"): %}
ip protocol udp ct mark 0x000000fa {{ counter }} {{ dynamic_direct_udp4 }} accept comment "Xray dynamic direct UDP4"
{% endif %}
{% if (general.dynamic_direct_tcp6 == "1"): %}
ip6 nexthdr tcp ct mark 0x000000fa {{ counter }} {{ dynamic_direct_tcp6 }} accept comment "Xray dynamic direct TCP6"
{% endif %}
{% if (general.dynamic_direct_udp6 == "1"): %}
ip6 nexthdr udp ct mark 0x000000fa {{ counter }} {{ dynamic_direct_udp6 }} accept comment "Xray dynamic direct UDP6"
{% endif %}
mark 0x000000fb {{ counter }} accept comment "Xray remarked from output"
{{ counter }} jump tp_spec_lan_mf comment "Xray FakeDNS / manual transparent proxy"
{% if (length(general.bypass_ifaces_v4 || []) > 0): %}
ip protocol tcp iifname { "{{ join('", "', general.bypass_ifaces_v4) }}" } {{ counter }} accept
ip protocol udp iifname { "{{ join('", "', general.bypass_ifaces_v4) }}" } {{ counter }} accept
{% endif %}
{% if (length(general.bypass_ifaces_v6 || []) > 0): %}
ip6 nexthdr tcp iifname { "{{ join('", "', general.bypass_ifaces_v6) }}" } {{ counter }} accept
ip6 nexthdr udp iifname { "{{ join('", "', general.bypass_ifaces_v6) }}" } {{ counter }} accept
{% endif %}
{% if (length(tp_spec_sm4_bp) > 0): %}
ip protocol tcp ether saddr @tp_spec_sm4_bp {{ counter }} accept
ip protocol udp ether saddr @tp_spec_sm4_bp {{ counter }} accept
{% endif %}
{% if (length(tp_spec_sm6_bp) > 0): %}
ip6 nexthdr tcp ether saddr @tp_spec_sm6_bp {{ counter }} accept
ip6 nexthdr udp ether saddr @tp_spec_sm6_bp {{ counter }} accept
{% endif %}
{% for (let i in extra_inbound_tcp_v4_map): %}
ip protocol tcp ether saddr @tp_spec_sm4_ft_{{ i }} {{ counter }} goto tp_spec_lan_ac
{% endfor %}
{% for (let i in extra_inbound_udp_v4_map): %}
ip protocol udp ether saddr @tp_spec_sm4_fu_{{ i }} {{ counter }} goto tp_spec_lan_ac
{% endfor %}
{% for (let i in extra_inbound_tcp_v6_map): %}
ip6 nexthdr tcp ether saddr @tp_spec_sm6_ft_{{ i }} {{ counter }} goto tp_spec_lan_ac
{% endfor %}
{% for (let i in extra_inbound_udp_v6_map): %}
ip6 nexthdr udp ether saddr @tp_spec_sm6_fu_{{ i }} {{ counter }} goto tp_spec_lan_ac
{% endfor %}
{% if (length(tp_spec_sm4_tp) > 0): %}
ip protocol tcp ether saddr @tp_spec_sm4_tp {{ counter }} goto tp_spec_lan_ac
ip protocol udp ether saddr @tp_spec_sm4_tp {{ counter }} goto tp_spec_lan_ac
{% endif %}
{% if (length(tp_spec_sm6_tp) > 0): %}
ip6 nexthdr tcp ether saddr @tp_spec_sm6_tp {{ counter }} goto tp_spec_lan_ac
ip6 nexthdr udp ether saddr @tp_spec_sm6_tp {{ counter }} goto tp_spec_lan_ac
{% endif %}
{% if (length(general.tproxy_ifaces_v4 || []) > 0): %}
ip protocol tcp iifname { "{{ join('", "', general.tproxy_ifaces_v4) }}" } {{ counter }} goto tp_spec_lan_ac
ip protocol udp iifname { "{{ join('", "', general.tproxy_ifaces_v4) }}" } {{ counter }} goto tp_spec_lan_ac
{% endif %}
{% if (length(general.tproxy_ifaces_v6 || []) > 0): %}
ip6 nexthdr tcp iifname { "{{ join('", "', general.tproxy_ifaces_v6) }}" } {{ counter }} goto tp_spec_lan_ac
ip6 nexthdr udp iifname { "{{ join('", "', general.tproxy_ifaces_v6) }}" } {{ counter }} goto tp_spec_lan_ac
{% endif %}
ip protocol tcp {{ counter }} accept
ip protocol udp {{ counter }} accept
ip6 nexthdr tcp {{ counter }} accept
ip6 nexthdr udp {{ counter }} accept
{{ counter }} accept
}
chain xray_output {
type route hook output priority mangle {{ firewall_priority }}; policy accept;
{% if (length(uids_direct) > 0): %}
meta skuid { {{ join(", ", uids_direct) }} } {{ counter }} accept
{% endif %}
{% if (length(gids_direct) > 0): %}
meta skgid { {{ join(", ", gids_direct) }} } {{ counter }} accept
{% endif %}
ip protocol tcp {{ counter }} goto tp_spec_wan_ac
ip protocol udp {{ counter }} goto tp_spec_wan_ac
ip6 nexthdr tcp {{ counter }} goto tp_spec_wan_ac
ip6 nexthdr udp {{ counter }} goto tp_spec_wan_ac
{{ counter }} accept
}
chain tp_spec_wan_ac {
ip protocol tcp mark 0x000000fc {{ counter }} {{ dynamic_direct_tcp4 }} accept comment "Xray direct outbound TCP4"
ip protocol udp mark 0x000000fc {{ counter }} {{ dynamic_direct_udp4 }} accept comment "Xray direct outbound UDP4"
ip6 nexthdr tcp mark 0x000000fc {{ counter }} {{ dynamic_direct_tcp6 }} accept comment "Xray direct outbound TCP6"
ip6 nexthdr udp mark 0x000000fc {{ counter }} {{ dynamic_direct_udp6 }} accept comment "Xray direct outbound UDP6"
meta mark 0x000000fd {{ counter }} accept comment "Xray transparent proxy outbound"
meta mark 0x000000fe {{ counter }} accept comment "Xray non-IP DNS query outbound"
meta mark {{ sprintf("0x%08x", general_mark) }} {{ counter }} accept comment "Xray specified mark {{ general_mark }} outbound"
{{ counter }} jump tp_spec_lan_mf
{% if (!tcp4_enabled): %}
ip protocol tcp {{ counter }} accept
{% endif %}
{% if (!udp4_enabled): %}
ip protocol udp {{ counter }} accept
{% endif %}
{% if (!tcp6_enabled): %}
ip6 nexthdr tcp {{ counter }} accept
{% endif %}
{% if (!udp6_enabled): %}
ip6 nexthdr udp {{ counter }} accept
{% endif %}
{{ counter }} goto tp_spec_lan_ac
}
chain tp_spec_lan_mf {
{% if (length(fakedns) > 0): %}
ip protocol tcp ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} {{ counter }} goto tp_spec_lan_fw comment "Xray FakeDNS IPv4 Pool TCP"
ip protocol udp ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} {{ counter }} goto tp_spec_lan_fw comment "Xray FakeDNS IPv4 Pool UDP"
ip6 nexthdr tcp ip6 daddr {{ general.pool_v6 || "fc00::/18" }} {{ counter }} goto tp_spec_lan_fw comment "Xray FakeDNS IPv6 Pool TCP"
ip6 nexthdr udp ip6 daddr {{ general.pool_v6 || "fc00::/18" }} {{ counter }} goto tp_spec_lan_fw comment "Xray FakeDNS IPv6 Pool UDP"
{% endif %}
{% if (length(manual_tproxy_source_ips) > 0): %}
ip protocol tcp ip daddr @tp_spec_dv4_mt {{ counter }} goto tp_spec_lan_fw comment "Xray manual transparent proxy TCP"
ip protocol udp ip daddr @tp_spec_dv4_mt {{ counter }} goto tp_spec_lan_fw comment "Xray manual transparent proxy UDP"
{% endif %}
{% if (length(wan_bp_dns_v4) > 0): %}
ip daddr . tcp dport @tp_spec_dp4_bp {{ counter }} accept
ip daddr . udp dport @tp_spec_dp4_bp {{ counter }} accept
{% endif %}
{% if (length(wan_bp_dns_v6) > 0): %}
ip6 daddr . tcp dport @tp_spec_dp6_bp {{ counter }} accept
ip6 daddr . udp dport @tp_spec_dp6_bp {{ counter }} accept
{% endif %}
{{ counter }} return
}
chain tp_spec_lan_ac {
{% if (length(wan_fw_ips_v4) > 0): %}
ip daddr @tp_spec_dv4_fw {{ counter }} goto tp_spec_lan_fw
{% endif %}
{% if (length(wan_fw_ips_v6) > 0): %}
ip6 daddr @tp_spec_dv6_fw {{ counter }} goto tp_spec_lan_fw
{% endif %}
{% if (ignore_tp_spec_def_gw == null): %}
ip daddr @tp_spec_dv4_dg {{ counter }} accept
{% endif %}
ip6 daddr @tp_spec_dv6_dg {{ counter }} accept
{% if (length(wan_bp_ips_v4) > 0): %}
ip daddr @tp_spec_dv4_bp {{ counter }} accept
{% endif %}
{% if (length(wan_bp_ips_v6) > 0): %}
ip6 daddr @tp_spec_dv6_bp {{ counter }} accept
{% endif %}
ip daddr @tp_spec_dv4_sp {{ counter }} accept
ip6 daddr @tp_spec_dv6_sp {{ counter }} accept
{{ counter }} goto tp_spec_lan_re
}
chain tp_spec_lan_re {
{% if (transparent_default_port_policy == "bypassed"): %}
{% if (length(wan_fw_tcp_ports) > 0): %}
tcp dport { {{ join(", ", wan_fw_tcp_ports) }} } {{ counter }} meta l4proto tcp goto tp_spec_lan_fw
{% endif %}
{% if (length(wan_fw_udp_ports) > 0): %}
udp dport { {{ join(", ", wan_fw_udp_ports) }} } {{ counter }} meta l4proto udp goto tp_spec_lan_fw
{% endif %}
{% else %}
{% if (length(wan_bp_tcp_ports) > 0): %}
tcp dport { {{ join(", ", wan_bp_tcp_ports) }} } {{ counter }} meta l4proto tcp accept
{% endif %}
{% if (length(wan_bp_udp_ports) > 0): %}
udp dport { {{ join(", ", wan_bp_udp_ports) }} } {{ counter }} meta l4proto udp accept
{% endif %}
meta l4proto tcp {{ counter }} goto tp_spec_lan_dd
meta l4proto udp {{ counter }} goto tp_spec_lan_dd
{% endif %}
{{ counter }} accept
}
chain tp_spec_lan_dd {
{% if (general.dynamic_direct_tcp4 == "1"): %}
ip protocol tcp ip daddr @tp_spec_dv4_dd {{ counter }} goto tp_spec_lan_ct comment "Xray dynamic direct TCP4"
{% endif %}
{% if (general.dynamic_direct_udp4 == "1"): %}
ip protocol udp ip daddr @tp_spec_dv4_dd {{ counter }} goto tp_spec_lan_ct comment "Xray dynamic direct UDP4"
{% endif %}
{% if (general.dynamic_direct_tcp6 == "1"): %}
ip6 nexthdr tcp ip6 daddr @tp_spec_dv6_dd {{ counter }} goto tp_spec_lan_ct comment "Xray dynamic direct TCP6"
{% endif %}
{% if (general.dynamic_direct_udp6 == "1"): %}
ip6 nexthdr udp ip6 daddr @tp_spec_dv6_dd {{ counter }} goto tp_spec_lan_ct comment "Xray dynamic direct UDP6"
{% endif %}
meta l4proto tcp {{ counter }} {{ dynamic_direct_conntrack_tcp }} goto tp_spec_lan_fw
meta l4proto udp {{ counter }} {{ dynamic_direct_conntrack_udp }} goto tp_spec_lan_fw
{{ counter }} accept
}
{% if (dynamic_direct_conntrack_tcp != "" || dynamic_direct_conntrack_udp != ""): %}
chain tp_spec_lan_ct {
{% if (dynamic_direct_conntrack_tcp != ""): %}
meta nfproto . tcp sport @tp_spec_ctt_dd {{ counter }} meta l4proto tcp goto tp_spec_lan_fw
{% endif %}
{% if (dynamic_direct_conntrack_udp != ""): %}
meta nfproto . udp sport @tp_spec_ctu_dd {{ counter }} meta l4proto udp goto tp_spec_lan_fw
{% endif %}
{{ counter }} ct mark set 0x000000fa accept comment "Xray dynamic direct successful registration"
}
{% endif %}
chain tp_spec_lan_fw {
{{ counter }} mark set 0x000000fb accept
}
{% if (length(fakedns) > 0): %}
{% if (general.fakedns_ping_response_prerouting == "1"): %}
chain xray_fakedns_ping_prerouting {
type nat hook prerouting priority dstnat {{ firewall_priority }}; policy accept;
ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} icmp type echo-request {{ counter }} redirect comment "Xray FakeDNS IPv4 Pool ICMP"
ip6 daddr {{ general.pool_v6 || "fc00::/18" }} icmpv6 type echo-request {{ counter }} redirect comment "Xray FakeDNS IPv6 Pool ICMPv6"
}
{% endif %}
{% if (general.fakedns_ping_response_output == "1"): %}
chain xray_fakedns_ping_output {
type nat hook output priority dstnat {{ firewall_priority }}; policy accept;
ip daddr {{ general.pool_v4 || "198.18.0.0/15" }} icmp type echo-request {{ counter }} redirect comment "Xray FakeDNS IPv4 Pool ICMP"
ip6 daddr {{ general.pool_v6 || "fc00::/18" }} icmpv6 type echo-request {{ counter }} redirect comment "Xray FakeDNS IPv6 Pool ICMPv6"
}
{% endif %}
{% endif %}