summaryrefslogtreecommitdiff
path: root/docs/configexamples/zone-policy.md
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-06 20:42:32 +0300
committerYuriy Andamasov <yuriy@vyos.io>2026-05-06 20:42:32 +0300
commit5d6fa52b8985f8068314aba26878a1d7d5cb84e5 (patch)
tree99359ff282846e26b5c5fa2b9b176b35b172809f /docs/configexamples/zone-policy.md
parent631e454d674ad5111d2b56a6964ead461894a1f6 (diff)
downloadvyos-documentation-5d6fa52b8985f8068314aba26878a1d7d5cb84e5.tar.gz
vyos-documentation-5d6fa52b8985f8068314aba26878a1d7d5cb84e5.zip
feat: flip swap mechanism — MD as primary, RST as override (Phase 1)
This is the first of three phases inverting the per-page swap mechanism so MD becomes the canonical primary and RST becomes the rare override. Phase 1 — file renames + conf.py exclude_patterns flip only: - Rename docs/**/md-<stem>.md to docs/**/<stem>.md (drop md- prefix) for all 254 stems previously listed in docs/_swap.txt - Rename docs/**/<stem>.rst to docs/**/rst-<stem>.rst (add rst- prefix) for the same 254 stems - Repurpose docs/_swap.txt as docs/_rst_overrides.txt; initially empty comment-only since no pages need the RST fallback right now - conf.py exclude_patterns flipped: rst-*.rst is now excluded by default instead of md-*.md - conf.py runtime-artifact references updated to _rst_override_state.json and _md_exclude.txt (Phase 2 will rewrite swap_sources.py to produce these names; for now no swap script runs because overrides list is empty) Phase 2 (next commit on this branch) will rewrite scripts/swap_sources.py with inverted rename direction, delete scripts/import_myst.py + tests, and update tests/test_swap_sources.py for the new semantics. Phase 3 will be the cleanup pass and ready-for-review flip. Generated by robots https://vyos.io
Diffstat (limited to 'docs/configexamples/zone-policy.md')
-rw-r--r--docs/configexamples/zone-policy.md417
1 files changed, 417 insertions, 0 deletions
diff --git a/docs/configexamples/zone-policy.md b/docs/configexamples/zone-policy.md
new file mode 100644
index 00000000..2cd773a9
--- /dev/null
+++ b/docs/configexamples/zone-policy.md
@@ -0,0 +1,417 @@
+---
+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.
+
+```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.webp
+:align: center
+:alt: Network Topology Diagram
+:width: 80%
+```
+
+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:
+
+```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.
+
+```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:
+
+```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.
+
+```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.
+
+```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.
+
+```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.
+
+```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.
+
+```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.
+
+```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:
+
+```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:
+
+```none
+rule 400 {
+ action accept
+ destination {
+ address 172.16.10.1
+ }
+ log enable
+ protocol 41
+ source {
+ address ip.of.tunnel.broker
+ }
+}
+```