summaryrefslogtreecommitdiff
path: root/docs/configexamples/zone-policy.rst
blob: d0101ebf1f27f6c2f1a2ff35331f2cfbf49d24a4 (plain)
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
:lastproofread: 2024-06-14

.. _examples-zone-policy:

Zone-Policy example
-------------------

.. note:: In :vytask:`T2199` the syntax of the zone configuration was changed.
   The zone configuration moved from ``zone-policy zone <name>`` to ``firewall
   zone <name>``.

Native IPv4 and IPv6
^^^^^^^^^^^^^^^^^^^^

We have three networks.

.. code-block:: none

  WAN - 172.16.10.0/24, 2001:0DB8:0:9999::0/64
  LAN - 192.168.100.0/24, 2001:0DB8:0:AAAA::0/64
  DMZ - 192.168.200.0/24, 2001:0DB8:0:BBBB::0/64


**This specific example is for a router on a stick, but is very easily
adapted for however many NICs you have**:


* Internet - 192.168.200.100 - TCP/80
* Internet - 192.168.200.100 - TCP/443
* Internet - 192.168.200.100 - TCP/25
* Internet - 192.168.200.100 - TCP/53
* VyOS acts as DHCP, DNS forwarder, NAT, router and firewall.
* 192.168.200.200/2001:0DB8:0:BBBB::200 is an internal/external DNS, web
  and mail (SMTP/IMAP) server.
* 192.168.100.10/2001:0DB8:0:AAAA::10 is the administrator's console. It
  can SSH to VyOS.
* LAN and DMZ hosts have basic outbound access: Web, FTP, SSH.
* LAN can access DMZ resources.
* DMZ cannot access LAN resources.
* Inbound WAN connect to DMZ host.

.. image:: /_static/images/zone-policy-diagram.png
   :width: 80%
   :align: center
   :alt: Network Topology Diagram

The VyOS interface is assigned the .1/:1 address of their respective
networks. WAN is on VLAN 10, LAN on VLAN 20, and DMZ on VLAN 30.

It will look something like this:

.. code-block:: none

  interfaces {
      ethernet eth0 {
          duplex auto
          hw-id 00:53:ed:6e:2a:92
          smp_affinity auto
          speed auto
          vif 10 {
              address 172.16.10.1/24
              address 2001:db8:0:9999::1/64
          }
          vif 20 {
              address 192.168.100.1/24
              address 2001:db8:0:AAAA::1/64
          }
          vif 30 {
              address 192.168.200.1/24
              address 2001:db8:0:BBBB::1/64
          }
      }
      loopback lo {
      }
  }


Zones Basics
^^^^^^^^^^^^

Each interface is assigned to a zone. The interface can be physical or
virtual such as tunnels (VPN, PPTP, GRE, etc) and are treated exactly
the same.

Traffic flows from zone A to zone B. That flow is what I refer to as a
zone-pair-direction. eg. A->B and B->A are two zone-pair-destinations.

Ruleset are created per zone-pair-direction.

I name rule sets to indicate which zone-pair-direction they represent.
eg. ZoneA-ZoneB or ZoneB-ZoneA. LAN-DMZ, DMZ-LAN.

In VyOS, you have to have unique Ruleset names. In the event of overlap,
I add a "-6" to the end of v6 rulesets. eg. LAN-DMZ, LAN-DMZ-6. This
allows for each auto-completion and uniqueness.

In this example we have 4 zones. LAN, WAN, DMZ, Local. The local zone is
the firewall itself.

If your computer is on the LAN and you need to SSH into your VyOS box,
you would need a rule to allow it in the LAN-Local ruleset. If you want
to access a webpage from your VyOS box, you need a rule to allow it in
the Local-LAN ruleset.

In rules, it is good to keep them named consistently. As the number of
rules you have grows, the more consistency you have, the easier your
life will be.

.. code-block:: none

  Rule 1 - State Established, Related
  Rule 2 - State Invalid
  Rule 100 - ICMP
  Rule 200 - Web
  Rule 300 - FTP
  Rule 400 - NTP
  Rule 500 - SMTP
  Rule 600 - DNS
  Rule 700 - DHCP
  Rule 800 - SSH
  Rule 900 - IMAPS

The first two rules are to deal with the idiosyncrasies of VyOS and
iptables.

Zones and Rulesets both have a default action statement. When using
Zone-Policies, the default action is set by the zone-policy statement
and is represented by rule 10000.

It is good practice to log both accepted and denied traffic. It can save
you significant headaches when trying to troubleshoot a connectivity
issue.

To add logging to the default rule, do:

.. code-block:: none

  set firewall name <ruleSet> default-log


By default, iptables does not allow traffic for established sessions to
return, so you must explicitly allow this. I do this by adding two rules
to every ruleset. 1 allows established and related state packets through
and rule 2 drops and logs invalid state packets. We place the
established/related rule at the top because the vast majority of traffic
on a network is established and the invalid rule to prevent invalid
state packets from mistakenly being matched against other rules. Having
the most matched rule listed first reduces CPU load in high volume
environments. Note: I have filed a bug to have this added as a default
action as well.

''It is important to note, that you do not want to add logging to the
established state rule as you will be logging both the inbound and
outbound packets for each session instead of just the initiation of the
session. Your logs will be massive in a very short period of time.''

In VyOS you must have the interfaces created before you can apply it to
the zone and the rulesets must be created prior to applying it to a
zone-policy.

I create/configure the interfaces first. Build out the rulesets for each
zone-pair-direction which includes at least the three state rules. Then
I setup the zone-policies.

Zones do not allow for a default action of accept; either drop or
reject. It is important to remember this because if you apply an
interface to a zone and commit, any active connections will be dropped.
Specifically, if you are SSH’d into VyOS and add local or the interface
you are connecting through to a zone and do not have rulesets in place
to allow SSH and established sessions, you will not be able to connect.

The following are the rules that were created for this example (may not
be complete), both in IPv4 and IPv6. If there is no IP specified, then
the source/destination address is not explicit.

.. code-block:: none

  WAN - DMZ:192.168.200.200 - tcp/80
  WAN - DMZ:192.168.200.200 - tcp/443
  WAN - DMZ:192.168.200.200 - tcp/25
  WAN - DMZ:192.168.200.200 - tcp/53
  WAN - DMZ:2001:0DB8:0:BBBB::200 - tcp/80
  WAN - DMZ:2001:0DB8:0:BBBB::200 - tcp/443
  WAN - DMZ:2001:0DB8:0:BBBB::200 - tcp/25
  WAN - DMZ:2001:0DB8:0:BBBB::200 - tcp/53

  DMZ - Local - tcp/53
  DMZ - Local - tcp/123
  DMZ - Local - tcp/67,68

  LAN - Local - tcp/53
  LAN - Local - tcp/123
  LAN - Local - tcp/67,68
  LAN:192.168.100.10 - Local - tcp/22
  LAN:2001:0DB8:0:AAAA::10 - Local - tcp/22

  LAN - WAN - tcp/80
  LAN - WAN - tcp/443
  LAN - WAN - tcp/22
  LAN - WAN - tcp/20,21

  DMZ - WAN - tcp/80
  DMZ - WAN - tcp/443
  DMZ - WAN - tcp/22
  DMZ - WAN - tcp/20,21
  DMZ - WAN - tcp/53
  DMZ - WAN - udp/53

  Local - WAN - tcp/80
  Local - WAN - tcp/443
  Local - WAN - tcp/20,21

  Local - DMZ - tcp/25
  Local - DMZ - tcp/67,68
  Local - DMZ - tcp/53
  Local - DMZ - udp/53

  Local - LAN - tcp/67,68

  LAN - DMZ - tcp/80
  LAN - DMZ - tcp/443
  LAN - DMZ - tcp/993
  LAN:2001:0DB8:0:AAAA::10 - DMZ:2001:0DB8:0:BBBB::200 - tcp/22
  LAN:192.168.100.10 - DMZ:192.168.200.200 - tcp/22

Since we have 4 zones, we need to setup the following rulesets.

.. code-block:: none

  Lan-wan
  Lan-local
  Lan-dmz
  Wan-lan
  Wan-local
  Wan-dmz
  Local-lan
  Local-wan
  Local-dmz
  Dmz-lan
  Dmz-wan
  Dmz-local

Even if the two zones will never communicate, it is a good idea to
create the zone-pair-direction rulesets and set default-log. This
will allow you to log attempts to access the networks. Without it, you
will never see the connection attempts.

This is an example of the three base rules.

.. code-block:: none

  name wan-lan {
    default-action drop
    default-log
    rule 1 {
      action accept
      state {
        established enable
        related enable
      }
    }
    rule 2 {
      action drop
      log enable
      state {
        invalid enable
      }
    }
  }


Here is an example of an IPv6 DMZ-WAN ruleset.

.. code-block:: none

  ipv6-name dmz-wan-6 {
    default-action drop
    default-log
    rule 1 {
      action accept
      state {
        established enable
        related enable
      }
    }
    rule 2 {
      action drop
      log enable
      state {
        invalid enable
    }
    rule 100 {
      action accept
      log enable
      protocol ipv6-icmp
    }
    rule 200 {
      action accept
      destination {
        port 80,443
      }
      log enable
      protocol tcp
    }
    rule 300 {
      action accept
      destination {
        port 20,21
      }
      log enable
      protocol tcp
    }
    rule 500 {
      action accept
      destination {
        port 25
      }
      log enable
      protocol tcp
      source {
        address 2001:db8:0:BBBB::200
      }
    }
    rule 600 {
      action accept
      destination {
        port 53
      }
      log enable
      protocol tcp_udp
      source {
        address 2001:db8:0:BBBB::200
      }
    }
    rule 800 {
      action accept
      destination {
      port 22
      }
      log enable
      protocol tcp
    }
  }

Once you have all of your rulesets built, then you need to create your
zone-policy.

Start by setting the interface and default action for each zone.

.. code-block:: none

  set firewall zone dmz default-action drop
  set firewall zone dmz interface eth0.30

In this case, we are setting the v6 ruleset that represents traffic
sourced from the LAN, destined for the DMZ. Because the zone-policy
firewall syntax is a little awkward, I keep it straight by thinking of
it backwards.

.. code-block:: none

  set firewall zone dmz from lan firewall ipv6-name lan-dmz-6

DMZ-LAN policy is LAN-DMZ. You can get a rhythm to it when you build out
a bunch at one time.

In the end, you will end up with something like this config. I took out
everything but the Firewall, Interfaces, and zone-policy sections. It is
long enough as is.


IPv6 Tunnel
^^^^^^^^^^^

If you are using a IPv6 tunnel from HE.net or someone else, the basis is
the same except you have two WAN interfaces. One for v4 and one for v6.

You would have 5 zones instead of just 4 and you would configure your v6
ruleset between your tunnel interface and your LAN/DMZ zones instead of
to the WAN.

LAN, WAN, DMZ, local and TUN (tunnel)

v6 pairs would be:

.. code-block:: none

  lan-tun
  lan-local
  lan-dmz
  tun-lan
  tun-local
  tun-dmz
  local-lan
  local-tun
  local-dmz
  dmz-lan
  dmz-tun
  dmz-local

Notice, none go to WAN since WAN wouldn't have a v6 address on it.

You would have to add a couple of rules on your wan-local ruleset to
allow protocol 41 in.

Something like:

.. code-block:: none

  rule 400 {
    action accept
    destination {
      address 172.16.10.1
    }
    log enable
    protocol 41
    source {
      address ip.of.tunnel.broker
    }
  }