|
|
|
|
@ -10,7 +10,7 @@ import time
|
|
|
|
|
from topology import COUNTRIES, NATS, NODES, WANS, wan |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def nat_rules(gateway): |
|
|
|
|
def nat_rules(gateway, stun_trial=False): |
|
|
|
|
clients = [node for node in NODES if node.nat == gateway.name] |
|
|
|
|
destinations = sorted({n.ip for n in NODES if not n.nat} | {g.ip for g in NATS}) |
|
|
|
|
lines = ["table ip lab {", |
|
|
|
|
@ -27,6 +27,19 @@ def nat_rules(gateway):
|
|
|
|
|
for index, destination in enumerate(destinations): |
|
|
|
|
port = 40000 + node.number * 100 + index |
|
|
|
|
lines.append(f"{match} ip daddr {destination} update @contacts {{ ip daddr . udp dport . {port} timeout 60s }}") |
|
|
|
|
# STUN-сценарий использует одного клиента шлюза. Его случайные тестовые порты |
|
|
|
|
# получают тот же класс NAT, что рабочий 32000; внешние порты остаются другими. |
|
|
|
|
trial = clients[0] |
|
|
|
|
if stun_trial: |
|
|
|
|
match = f' oifname "wan" ip saddr {trial.ip} udp sport 49152-65535' |
|
|
|
|
if gateway.mode == "cone": |
|
|
|
|
lines.append(f"{match} update @active {{ udp sport timeout 60s }}") |
|
|
|
|
elif gateway.mode == "restricted": |
|
|
|
|
lines.append(f"{match} update @contacts {{ ip daddr . udp dport . udp sport timeout 60s }}") |
|
|
|
|
else: |
|
|
|
|
for index, destination in enumerate(destinations): |
|
|
|
|
port = 40000 + trial.number * 100 + index |
|
|
|
|
lines.append(f"{match} ip daddr {destination} update @contacts {{ ip daddr . udp dport . {port} timeout 60s }}") |
|
|
|
|
# Запрещённый вход отсекается ДО conntrack. Иначе первая неуспешная |
|
|
|
|
# входящая проба закрепляет tuple без DNAT и блокирует последующее открытие. |
|
|
|
|
lines += [" }", " chain ingress_guard { type filter hook prerouting priority raw; policy accept;"] |
|
|
|
|
@ -40,6 +53,10 @@ def nat_rules(gateway):
|
|
|
|
|
else: |
|
|
|
|
lines.append(f"{match} ip saddr . udp sport . udp dport @contacts accept") |
|
|
|
|
lines.append(f"{match} counter drop") |
|
|
|
|
if stun_trial and gateway.mode != "strict": |
|
|
|
|
match = ' iifname "wan" udp dport 49152-65535' |
|
|
|
|
guard = "udp dport @active" if gateway.mode == "cone" else "ip saddr . udp sport . udp dport @contacts" |
|
|
|
|
lines += [f"{match} {guard} accept", f"{match} counter drop"] |
|
|
|
|
lines += [" }", " chain prerouting { type nat hook prerouting priority dstnat; policy accept;"] |
|
|
|
|
for node in clients: |
|
|
|
|
match = f' iifname "wan" udp dport {node.mapped_port}' |
|
|
|
|
@ -47,6 +64,9 @@ def nat_rules(gateway):
|
|
|
|
|
lines.append(f"{match} udp dport @active dnat to {node.ip}:{node.udp_port}") |
|
|
|
|
elif gateway.mode == "restricted": |
|
|
|
|
lines.append(f"{match} ip saddr . udp sport . udp dport @contacts dnat to {node.ip}:{node.udp_port}") |
|
|
|
|
if stun_trial and gateway.mode != "strict": |
|
|
|
|
guard = "udp dport @active" if gateway.mode == "cone" else "ip saddr . udp sport . udp dport @contacts" |
|
|
|
|
lines.append(f' iifname "wan" udp dport 49152-65535 {guard} dnat to {trial.ip}') |
|
|
|
|
lines += [" }", " chain postrouting { type nat hook postrouting priority srcnat; policy accept;"] |
|
|
|
|
for node in clients: |
|
|
|
|
match = f' oifname "wan" ip saddr {node.ip} udp sport {node.udp_port}' |
|
|
|
|
@ -56,6 +76,14 @@ def nat_rules(gateway):
|
|
|
|
|
lines.append(f"{match} ip daddr {destination} snat to {gateway.ip}:{port}") |
|
|
|
|
else: |
|
|
|
|
lines.append(f"{match} snat to {gateway.ip}:{node.mapped_port}") |
|
|
|
|
if stun_trial: |
|
|
|
|
match = f' oifname "wan" ip saddr {trial.ip} udp sport 49152-65535' |
|
|
|
|
if gateway.mode == "strict": |
|
|
|
|
for index, destination in enumerate(destinations): |
|
|
|
|
port = 40000 + trial.number * 100 + index |
|
|
|
|
lines.append(f"{match} ip daddr {destination} snat to {gateway.ip}:{port}") |
|
|
|
|
else: |
|
|
|
|
lines.append(f"{match} snat to {gateway.ip}") |
|
|
|
|
lines += [' oifname "wan" masquerade', " }", |
|
|
|
|
" chain forward { type filter hook forward priority filter; policy drop;", |
|
|
|
|
" ct state established,related accept", ' iifname "lan" oifname "wan" accept', |
|
|
|
|
|