-
Notifications
You must be signed in to change notification settings - Fork 759
/
ipfw.conf
222 lines (201 loc) · 12.3 KB
/
ipfw.conf
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
{# Macro import #}
{% from 'OPNsense/IPFW/rules.macro' import convert_address %}
{# collect interfaces list (with / without captive portal enabled) #}
{% set cp_interface_list = [] %}
{% set no_cp_interface_list = [] %}
{% if helpers.exists('OPNsense.captiveportal.zones.zone') %}
{% for intf_key,interface in interfaces.items()%}
{% set is_cp=[] %}
{% for cp_item in helpers.toList('OPNsense.captiveportal.zones.zone') %}
{% for cp_intf in cp_item.interfaces.split(',') %}
{% if intf_key == cp_intf %}
{% if cp_item.enabled|default('0') == '1' %}
{% do cp_interface_list.append({'zone':cp_item.description, 'zoneid':cp_item.zoneid,'if':interface.if, 'obj':cp_item}) %}
{% do is_cp.append(1) %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
{% if not is_cp%}
{% do no_cp_interface_list.append(interface) %}
{% endif %}
{% endfor %}
{% else %}
{% for intf_key,interface in interfaces.items() %}
{% do no_cp_interface_list.append(interface) %}
{% endfor %}
{% endif %}
#======================================================================================
# flush ruleset
#======================================================================================
flush
#======================================================================================
# define dummynet pipes
#======================================================================================
{% if helpers.exists('OPNsense.TrafficShaper.pipes.pipe') %}
{% for pipe in helpers.toList('OPNsense.TrafficShaper.pipes.pipe') %}
pipe {{ pipe.number }} config bw {{ pipe.bandwidth }}{{ pipe.bandwidthMetric }}/s{%
if pipe.queue %} queue {{ pipe.queue }}{%
if pipe.queueMetric != 'slots' %}{{pipe.queueMetric}}{% endif %}{% endif
%}{% if pipe.buckets %} buckets {{ pipe.buckets }}{% endif
%}{% if pipe.mask != 'none' %} mask {{ pipe.mask }} 0xffffffff {% endif %}{%
if pipe.delay|default('') != '' %} delay {{pipe.delay}} {% endif %} type {%
if pipe.scheduler|default('') != '' %} {{pipe.scheduler}} {% else %} wf2q+ {% endif %}{%
if pipe.codel_enable|default('0') == '1' and pipe.scheduler != 'fq_codel' %} codel {% endif %}{%
if pipe.codel_enable|default('0') == '1' or pipe.scheduler == 'fq_codel' %}{%
if pipe.codel_target|default('') != ''%} target {{pipe.codel_target}} {% endif %}{%
if pipe.codel_interval|default('') != ''%} interval {{pipe.codel_interval}} {% endif %}{%
if pipe.codel_ecn_enable|default('0') == '1'%} ecn {% else %} noecn {% endif %} {%
if pipe.scheduler == 'fq_codel' %} {%
if pipe.fqcodel_quantum|default('') != '' %} quantum {{pipe.fqcodel_quantum}} {% endif %} {%
if pipe.fqcodel_limit|default('') != '' %} limit {{pipe.fqcodel_limit}} {% endif %} {%
if pipe.fqcodel_flows|default('') != '' %} flows {{pipe.fqcodel_flows}} {% endif %}
{% endif %}{%
elif pipe.pie_enable|default('0') == '1' and pipe.scheduler != 'fq_pie' %} pie {% endif %}
{% endfor %}
{% endif %}
#======================================================================================
# define dummynet queues
#======================================================================================
{% if helpers.exists('OPNsense.TrafficShaper.queues.queue') %}
{% for queue in helpers.toList('OPNsense.TrafficShaper.queues.queue') %}
{% if helpers.getUUIDtag(queue.pipe) in ['pipe'] %}
queue {{ queue.number }} config pipe {{ helpers.getUUID(queue.pipe).number
}}{% if queue.buckets %} buckets {{ queue.buckets }}{% endif %}{% if queue.mask != 'none' %} mask {{ queue.mask }} 0xffffffff {% endif %} weight {{ queue.weight }}{%
if queue.codel_enable|default('0') == '1' %} codel {%
if queue.codel_target|default('') != ''%} target {{queue.codel_target}} {% endif %}{%
if queue.codel_interval|default('') != ''%} interval {{queue.codel_interval}} {% endif %}{%
if queue.codel_ecn_enable|default('0') == '1'%} ecn {% else %} noecn {% endif %}{%
elif queue.pie_enable|default('0') == '1' %} pie
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
#======================================================================================
# general purpose rules 1...1000
#======================================================================================
add 100 allow pfsync from any to any
add 110 allow carp from any to any
# layer 2: pass ARP
add 120 pass layer2 mac-type arp,rarp
# OPNsense requires for WPA
add 130 pass layer2 mac-type 0x888e,0x88c7
# PPP Over Ethernet Session Stage/Discovery Stage
add 140 pass layer2 mac-type 0x8863,0x8864
# layer 2: block anything else non-IP(v4/v6)
add 150 deny layer2 not mac-type ip,ipv6
# allow traffic send from localhost
add 200 skipto 60000 ipv6 from ::1 to any
add 201 skipto 60000 ipv4 from 127.0.0.0/8 to any
add 202 skipto 60000 ipv6 from any to ::1
add 203 skipto 60000 ipv4 from any to 127.0.0.0/8
#======================================================================================
# Allow traffic to this host
#======================================================================================
{% for item in cp_interface_list %}
add {{loop.index + 1000}} skipto 60000 udp from any to me dst-port 53 via {{item.if}} keep-state
add {{loop.index + 1000}} skipto 60000 ip from any to { 255.255.255.255 or me } in via {{item.if}}
add {{loop.index + 1000}} skipto 60000 ip from { 255.255.255.255 or me } to any out via {{item.if}}
add {{loop.index + 1000}} skipto 60000 icmp from { 255.255.255.255 or me } to any out via {{item.if}} icmptypes 0
add {{loop.index + 1000}} skipto 60000 icmp from any to { 255.255.255.255 or me } in via {{item.if}} icmptypes 8
{% endfor %}
{% for item in cp_interface_list %}
#===================================================================================
# zone {{item.zone}} ({{item.zoneid}}) / {{item.if}} configuration
#===================================================================================
{# authenticated clients #}
add {{3000 + item.zoneid|int }} skipto tablearg ip from table({{item.zoneid|int}}) to any via {{item.if}}
add {{3000 + item.zoneid|int }} skipto tablearg ip from any to table({{item.zoneid|int}}) via {{item.if}}
# Allowed traffic heading into this zone #
{% if item.obj.interfaces_inbound|default('') != '' %}
{% for inbound_if in item.obj.interfaces_inbound.split(',') if helpers.physical_interface(inbound_if)%}
add {{3000 + item.zoneid|int }} skipto 60000 ip from any to any recv {{helpers.physical_interface(inbound_if)}} xmit {{item.if}} keep-state
{% endfor %}
{% endif %}
{% endfor %}
#======================================================================================
# redirect non-authenticated clients to captive portal @ local port 8000 + zoneid
#======================================================================================
{% for item in cp_interface_list %}
add {{5000 + item.zoneid|int }} fwd 127.0.0.1,{{ item.zoneid|int + 8000 }} tcp from any to any dst-port 443 in via {{item.if}}
add {{5000 + item.zoneid|int }} allow ip from any to any dst-port 443 via {{item.if}}
add {{5000 + item.zoneid|int }} fwd 127.0.0.1,{{ item.zoneid|int + 9000 }} tcp from any to any dst-port 80 in via {{item.if}}
add {{5000 + item.zoneid|int }} allow ip from any to any dst-port 80 via {{item.if}}
{% endfor %}
#======================================================================================
# accept traffic from all interfaces not used by captive portal
#======================================================================================
# let the responses from the captive portal web server back out
add 6000 skipto 60000 tcp from any to any out
# forward unauthorized traffic from captiveportal interfaces to block rule
{% for item in cp_interface_list %}
add {{6001 + loop.index }} skipto 65534 all from any to any via {{item.if}}
{% endfor %}
# send all the rest to the traffic shaper rules
add 6199 skipto 60000 all from any to any
#======================================================================================
# 30000 .... 49999 reserved for captive portal accounting rules
#======================================================================================
#======================================================================================
# traffic shaping section, authorized traffic
#======================================================================================
add 60000 return via any
{% if helpers.exists('OPNsense.TrafficShaper.rules.rule') %}
{% for rule in helpers.toList('OPNsense.TrafficShaper.rules.rule', 'sequence', 'int') %}
{% if helpers.getUUIDtag(rule.target) in ['pipe','queue'] %}
{% if helpers.physical_interface(rule.interface) and rule.enabled|default('0') == '1' %}
{% if helpers.getUUID(rule.target).enabled|default('0') == '1' %}
{% if helpers.getUUIDtag(rule.target) == 'pipe' or
helpers.getUUID(helpers.getUUID(rule.target).pipe).enabled|default('0') == '1'
%}
{% if rule.interface2 and helpers.physical_interface(rule.interface2) %}
{# 2 interface defined, use both to match packets (2 rules) #}
{% if rule.direction == 'in' or not rule.direction %}
add {{loop.index + 60000}} {{ helpers.getUUIDtag(rule.target) }} {{
helpers.getUUID(rule.target).number }} {{ rule.proto.split('_')[0] }} from {%
if rule.source_not|default('0') == '1' %}not {% endif %}{{ convert_address(rule, 'source') }} to {%
if rule.destination_not|default('0') == '1' %}not {% endif %}{{convert_address(rule, 'destination')
}} src-port {{ rule.src_port }} dst-port {{ rule.dst_port }} recv {{
helpers.physical_interface(rule.interface) }} {%
if rule.proto.split('_')[1]|default('') == 'ack' %} {{ rule.proto.split('_')[2]|default('') }} tcpflags ack {% endif %}{%
if rule.iplen|default('') != '' %} iplen 1-{{ rule.iplen }}{% endif %}{%
if rule.dscp|default('') != '' %} dscp {{ rule.dscp }}{% endif %}
xmit {{helpers.physical_interface(rule.interface2)
}} // {{ (rule['@uuid'] + " " + rule.interface + " -> " + rule.interface2 + ": " + helpers.getUUID(rule.target).description)[0:78] }}
{% endif %}
{% if rule.direction == 'out' or not rule.direction %}
add {{loop.index + 60000}} {{ helpers.getUUIDtag(rule.target) }} {{
helpers.getUUID(rule.target).number }} {{ rule.proto.split('_')[0] }} from {%
if rule.source_not|default('0') == '1' %}not {% endif %}{{ convert_address(rule, 'source') }} to {%
if rule.destination_not|default('0') == '1' %}not {% endif %}{{convert_address(rule, 'destination')
}} src-port {{ rule.src_port }} dst-port {{ rule.dst_port }} xmit {{
helpers.physical_interface(rule.interface) }} {%
if rule.proto.split('_')[1]|default('') == 'ack' %} {{ rule.proto.split('_')[2]|default('') }} tcpflags ack {% endif %}{%
if rule.iplen|default('') != '' %} iplen 1-{{ rule.iplen }}{% endif %}{%
if rule.dscp|default('') != '' %} dscp {{ rule.dscp }}{% endif %}
recv {{helpers.physical_interface(rule.interface2)
}} // {{ (rule['@uuid'] + " " + rule.interface2 + " -> " + rule.interface + ": " + helpers.getUUID(rule.target).description)[0:78] }}
{% endif %}
{% else %}
{# normal, single interface situation #}
add {{loop.index + 60000}} {{ helpers.getUUIDtag(rule.target) }} {{
helpers.getUUID(rule.target).number }} {{ rule.proto.split('_')[0] }} from {%
if rule.source_not|default('0') == '1' %}not {% endif %}{{ convert_address(rule, 'source') }} to {%
if rule.destination_not|default('0') == '1' %}not {% endif %}{{convert_address(rule, 'destination')
}} src-port {{ rule.src_port }} dst-port {{ rule.dst_port }} {{rule.direction}} {%
if rule.proto.split('_')[1]|default('') == 'ack' %}{{ rule.proto.split('_')[2]|default('') }} tcpflags ack {% endif %} {%
if rule.iplen|default('') != '' %} iplen 1-{{ rule.iplen }}{% endif %}{%
if rule.dscp|default('') != '' %} dscp {{ rule.dscp }}{% endif %} via {{
helpers.physical_interface(rule.interface)
}} // {{ (rule['@uuid'] + " " + rule.interface + ": " + helpers.getUUID(rule.target).description)[0:78] }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
# pass authorized
add 65533 pass ip from any to any
# block all unmatched
add 65534 deny all from any to any