1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#!/usr/sbin/nft -f
# Start with clean NAT table
flush table nat
{% if helper_functions == 'remove' %}
{# NAT if going to be disabled - remove rules and targets from nftables #}
{% set base_command = "delete rule ip raw" %}
{{ base_command }} PREROUTING handle {{ pre_ct_ignore }}
{{ base_command }} OUTPUT handle {{ out_ct_ignore }}
{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }}
{{ base_command }} OUTPUT handle {{ out_ct_conntrack }}
delete chain ip raw NAT_CONNTRACK
{% elif helper_functions == 'add' %}
{# NAT if enabled - add targets to nftables #}
add chain ip raw NAT_CONNTRACK
add rule ip raw NAT_CONNTRACK counter accept
{% set base_command = "add rule ip raw" %}
{{ base_command }} PREROUTING position {{ pre_ct_ignore }} counter jump VYATTA_CT_HELPER
{{ base_command }} OUTPUT position {{ out_ct_ignore }} counter jump VYATTA_CT_HELPER
{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK
{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK
{% endif %}
{% macro nat_rule(rule, chain) %}
{% set src_addr = "ip saddr " + rule.source_address if rule.source_address %}
{% set dst_addr = "ip daddr " + rule.dest_address if rule.dest_address %}
{# negated port groups need special treatment, move != in front of { } group #}
{% if rule.source_port.startswith('!=') %}
{% set src_port = "sport != { " + rule.source_port.replace('!=','') +" }" if rule.source_port %}
{% else %}
{% set src_port = "sport { " + rule.source_port +" }" if rule.source_port %}
{% endif %}
{# negated port groups need special treatment, move != in front of { } group #}
{% if rule.dest_port.startswith('!=') %}
{% set dst_port = "dport != { " + rule.dest_port.replace('!=','') +" }" if rule.dest_port %}
{% else %}
{% set dst_port = "dport { " + rule.dest_port +" }" if rule.dest_port %}
{% endif %}
{% set comment = "DST-NAT-" + rule.number %}
{% if chain == "PREROUTING" %}
{% set interface = " iifname \"" + rule.interface_in + "\"" %}
{% set trns_addr = "dnat to " + rule.translation_address %}
{% elif chain == "POSTROUTING" %}
{% set interface = " oifname \"" + rule.interface_out + "\"" %}
{% set trns_addr = rule.translation_address %}
{% if rule.translation_address != 'masquerade' %}
{% set trns_addr = "snat to " + trns_addr %}
{% endif %}
{% endif %}
{% set trns_port = ":" + rule.translation_port if rule.translation_port %}
{% if rule.protocol == "tcp_udp" %}
{% set protocol = "tcp" %}
{% set comment = comment + " tcp_udp" %}
{% else %}
{% set protocol = rule.protocol %}
{% endif %}
{% if rule.log %}
{% set base_log = "[NAT-DST-" + rule.number %}
{% if rule.exclude %}
{% set log = base_log + "-EXCL]" %}
{% elif rule.translation_address == 'masquerade' %}
{% set log = base_log + "-MASQ]" %}
{% else %}
{% set log = base_log + "]" %}
{% endif %}
{% endif %}
{% if rule.exclude %}
{# rule has been marked as "exclude" thus we simply return here #}
{% set trns_addr = "return" %}
{% set trns_port = "" %}
{% endif %}
{% set output = "add rule ip nat " + chain + interface %}
{% if protocol != "all" %}
{% set output = output + " ip protocol " + protocol %}
{% endif %}
{% if src_addr %}
{% set output = output + " " + src_addr %}
{% endif %}
{% if src_port %}
{% set output = output + " " + protocol + " " + src_port %}
{% endif %}
{% if dst_addr %}
{% set output = output + " " + dst_addr %}
{% endif %}
{% if dst_port %}
{% set output = output + " " + protocol + " " + dst_port %}
{% endif %}
{# Count packets #}
{% set output = output + " counter" %}
{# Special handling of log option, we must repeat the entire rule before the #}
{# NAT translation options are added, this is essential #}
{% if log %}
{% set log_output = output + " log prefix \"" + log + "\" comment \"" + comment + "\"" %}
{% endif %}
{% if trns_addr %}
{% set output = output + " " + trns_addr %}
{% endif %}
{% if trns_port %}
{# Do not add a whitespace here, translation port must be directly added after IP address #}
{# e.g. 192.0.2.10:3389 #}
{% set output = output + trns_port %}
{% endif %}
{% if comment %}
{% set output = output + " comment \"" + comment + "\"" %}
{% endif %}
{{ log_output if log_output }}
{{ output }}
{# Special handling if protocol is tcp_udp, we must repeat the entire rule with udp as protocol #}
{% if rule.protocol == "tcp_udp" %}
{# Beware of trailing whitespace, without it the comment tcp_udp will be changed to udp_udp #}
{{ log_output | replace("tcp ", "udp ") if log_output }}
{{ output | replace("tcp ", "udp ") }}
{% endif %}
{% endmacro %}
#
# Destination NAT rules build up here
#
{% for rule in destination if not rule.disabled -%}
{{ nat_rule(rule, 'PREROUTING') }}
{% endfor %}
#
# Source NAT rules build up here
#
{% for rule in source if not rule.disabled -%}
{{ nat_rule(rule, 'POSTROUTING') }}
{% endfor %}
|