
Part 1 Recap
In Part 1 of this series, we installed VyOS and created an initial configuration. Now we can start working towards making our router functional. We’re going to start by getting IP connectivity with our provider.
Identifying the Interface
Before we can start configuring VyOS to receive an IP, we first need to determine what interface we need to configure. The port numbering may not be obvious between VyOS and your Mini PC. You can plug something into one of the ports. It doesn’t have to be your internet connection, you just need VyOS to see that something was plugged in.
Once it’s plugged in, type the Op Mode command “show interfaces” to see all interfaces and their status. We’re specifically looking for the value under the “S/L” column. The first value shows whether the interface is enabled at the configuration level. The second value shows whether it is up at the physical level (e.g. connected). You can see in my output that “eth1” is “u/u”, which means that is the interface that I plugged into.
admin@GK41:~$ show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface IP Address MAC VRF MTU S/L Description
----------- ------------ ----------------- ------- ----- ----- -------------
eth1 - 84:47:09:2d:a9:80 default 1500 u/u
eth2 - 84:47:09:2d:a9:82 default 1500 u/D
lo 127.0.0.1/8 00:00:00:00:00:00 default 65536 u/u
::1/128
Remember what port you plugged into. If your device has a lot of ports, you may want to label your ports.
How do you get your IP from your provider?
You will typically get your IP from your provider via DHCP, but some ISPs will give you a static IP and gateway. You need to know this information before continuing. I’ll show both methods.
Getting an IP from DHCP
To configure our interface to get an IP address from DHCP, it is very simple. We can type the following command from Conf Mode (replace “eth1” if your interface is not “eth1”). It’s also a good idea to give your interface a description so we know it’s the interface that is going to the internet.
Remember, to enter Conf Mode, type “configure”
set interfaces ethernet eth1 description "Internet"
set interfaces ethernet eth1 address dhcp
commit
Don’t forget to commit your configuration.
We can verify that we got an IP with that same “show interfaces” command. You can see we now have an IP on that interface.
admin@GK41# run show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface IP Address MAC VRF MTU S/L Description
----------- -------------- ----------------- ------- ----- ----- -------------
eth1 xx.x.95.244/24 84:47:09:2d:a9:80 default 1500 u/u Internet
eth2 - 84:47:09:2d:a9:82 default 1500 u/D
lo 127.0.0.1/8 00:00:00:00:00:00 default 65536 u/u
::1/128
NOTE: You may have seen that I typed “run” in front of that command. That is because I typed an Op Mode command from Conf Mode. The “run” command allows us to run an Op Mode command without needing to drop back down to Op Mode, which would get frustrating pretty quickly if you were doing a lot of configuration and needed to verify our progress frequently.
When getting an IP from DHCP, you will typically also get a default route that can be used to access everything on the internet. We can verify that with the “show ip route” command.
admin@GK41# run show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
f - OpenFabric,
> - selected route, * - FIB route, q - queued, r - rejected, b - backup
t - trapped, o - offload failure
S>* 0.0.0.0/0 [210/0] via xx.x.95.1, eth1, weight 1, 00:02:38
C>* xx.x.95.0/24 is directly connected, eth1, 00:03:16
Configuring a Static IP and Gateway
If the provider gave a static IP and gateway, you won’t be able to use DHCP. You will need to manually configure these. To configure the interface’s IP, you can use this command:
set interfaces ethernet eth1 description "Internet"
set interfaces ethernet eth1 address xx.x.95.244/24
You will also need to manually create the default route. You can do that with this:
set protocols static route 0.0.0.0/0 next-hop xx.x.95.1
NOTE: The next hop is the gateway that your ISP gave you for the static assignment.
And of course don’t forget to commit. We should see that we have an IP on the interface and a default route.
commit
admin@GK41# run show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface IP Address MAC VRF MTU S/L Description
----------- -------------- ----------------- ------- ----- ----- -------------
eth1 xx.x.95.244/24 84:47:09:2d:a9:80 default 1500 u/u Internet
eth2 - 84:47:09:2d:a9:82 default 1500 u/D
lo 127.0.0.1/8 00:00:00:00:00:00 default 65536 u/u
::1/128
admin@GK41# run show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
f - OpenFabric,
> - selected route, * - FIB route, q - queued, r - rejected, b - backup
t - trapped, o - offload failure
S>* 0.0.0.0/0 [1/0] via xx.x.95.1, eth1, weight 1, 00:00:08
C>* xx.x.95.0/24 is directly connected, eth1, 00:00:39
Testing Connectivity
We should now be able to ping the internet. We can ping a public DNS anycast server like 1.1.1.1, 4.2.2.2, 8.8.8.8, or 9.9.9.9.
admin@GK41# run ping 4.2.2.2
PING 4.2.2.2 (4.2.2.2) 56(84) bytes of data.
64 bytes from 4.2.2.2: icmp_seq=1 ttl=58 time=7.94 ms
64 bytes from 4.2.2.2: icmp_seq=2 ttl=58 time=5.07 ms
^C
--- 4.2.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 5.070/6.507/7.944/1.437 ms
You can see that we’re able to ping the internet
NOTE: You can press ctrl+c to stop the ping
We can also try to ping something like http://www.google.com.
admin@GK41# run ping www.google.com
ping: Unknown host: www.google.com
We see that we can’t resolve hostnames, this is because we don’t have an upstream DNS configured. We can configure one of those public anycast DNS servers I just mentioned as our name-server.
set system name-server 4.2.2.2
commit
Let’s try that ping again.
admin@GK41# run ping www.google.com
PING www.google.com (172.253.115.105) 56(84) bytes of data.
64 bytes from bg-in-f105.1e100.net (172.253.115.105): icmp_seq=1 ttl=59 time=6.86 ms
64 bytes from bg-in-f105.1e100.net (172.253.115.105): icmp_seq=2 ttl=59 time=6.06 ms
^C
--- www.google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 6.061/6.460/6.860/0.399 ms
Configuring the Firewall
Before we consider connecting users to our router, we need secure it by configuring the firewall.
VyOS uses nftables as it’s firewall from version 1.4 forward. I won’t be focused on versions before 1.4 in this series.
nftables uses 3 chains to filter traffic, the Input, Output, and Forward chains. Here’s a brief description of the use for each chain.
- Input – This is traffic that is destined for the router itself, like trying to ping an IP on the router
- Output – This is traffic that originated from the router itself, like trying to ping something from the router.
- Forward – This is traffic that goes through the router, like traffic from a host connected to the router, trying to reach the internet.
We’re going to start with the Input chain since that is traffic that is trying to reach our router.
The Input Chain
Our rules for the input chain will be simple. All traffic to our router from the internet will be denied, unless it is return traffic from traffic we initiated.
We start by configuring the default action for the chain. This is how we say to deny all traffic. (don’t commit until you complete the whole section).
set firewall ipv4 input filter default-action drop
NOTE: There are a few actions that we can take. “drop” is preferred since it denies packets silently, whereas using something like “reject” tells the remote end that we denied the traffic.
Now we need to allow traffic in the input chain if we originated it (like us pinging the internet).
set firewall ipv4 input filter rule 10 action 'accept'
set firewall ipv4 input filter rule 10 state 'established'
set firewall ipv4 input filter rule 10 state 'related'
A quick note on “state”:
Stateful firewalls allow for a scalable mechanism to allow traffic provided we initiated it from the trusted side of our network. This prevents the need to explicitly match traffic in both directions, which isn’t scalable.
- Established – This means that we have originated the traffic already, so allow the return traffic if that traffic is part of that connection.
- Related – This means that the traffic is related to the original connection, but is not the connection itself, like ICMP Errors.
We also need to scope the rule to what interfaces it applies to. If you don’t put an interface here, it means it can come in on any interface.
set firewall ipv4 input filter rule 10 inbound-interface name eth1
Don’t forget to give the rule a useful description.
set firewall ipv4 input filter rule 10 description 'Allow Return traffic destined to the router'
Our full rule should look something like this:
admin@GK41# compare commands
set firewall ipv4 input filter default-action 'drop'
set firewall ipv4 input filter rule 10 action 'accept'
set firewall ipv4 input filter rule 10 description 'Allow Return traffic destined to the router'
set firewall ipv4 input filter rule 10 inbound-interface name 'eth1'
set firewall ipv4 input filter rule 10 state 'established'
set firewall ipv4 input filter rule 10 state 'related'
If everything looks good, we can commit the config. When making changes to the firewall, it’s a good idea to get into the practice of using “commit-confirm” so we don’t accidentally kill our access to the router.
admin@GK41# save
Warning: you have uncommitted changes that will not be saved.
admin@GK41# commit-confirm 5
commit-confirm will automatically reboot in 5 minutes unless changes
are confirmed.
Proceed ? [Y/n] y
Initialized commit-confirm; 5 minutes to confirm before reboot
If you still have connection to your router, you can confirm and save the configuration.
admin@GK41# confirm
Reboot timer stopped
admin@GK41# save
Let’s try to ping the internet again.
admin@GK41# run ping 4.2.2.2
PING 4.2.2.2 (4.2.2.2) 56(84) bytes of data.
64 bytes from 4.2.2.2: icmp_seq=1 ttl=58 time=8.74 ms
64 bytes from 4.2.2.2: icmp_seq=2 ttl=58 time=7.08 ms
^C
--- 4.2.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 7.083/7.910/8.737/0.827 ms
You can see that we still have connectivity to the internet. We can also check if we have ‘hits’ on the input chain.
admin@GK41# run show firewall ipv4 input filter
Ruleset Information
---------------------------------
ipv4 Firewall "input filter"
Rule Action Protocol Packets Bytes Conditions
------- -------- ---------- --------- ------- --------------------------------------------------------
10 accept all 2 168 ct state { established, related } iifname "eth1" accept
default drop all 14 448
You can see that we sent 2 pings, and we received 2 packets (the returned pings) on our rule matching stateful traffic. So our rule is working.
The Output Chain
Our output chain will be even simpler, we fully trust our router, so we can just let the default-action be accept.
set firewall ipv4 output filter default-action accept
admin@GK41# save
Warning: you have uncommitted changes that will not be saved.
admin@GK41# commit-confirm 5
commit-confirm will automatically reboot in 5 minutes unless changes
are confirmed.
Proceed ? [Y/n] y
Initialized commit-confirm; 5 minutes to confirm before reboot
admin@GK41# confirm
Reboot timer stopped
admin@GK41# save
We can check that we can still ping, but we didn’t really change anything, since the absence of a configured chain is already a default accept.
admin@GK41# run ping 4.2.2.2
PING 4.2.2.2 (4.2.2.2) 56(84) bytes of data.
64 bytes from 4.2.2.2: icmp_seq=1 ttl=58 time=9.60 ms
^C
--- 4.2.2.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 9.595/9.595/9.595/0.000 ms
admin@GK41# run show firewall ipv4 output filter
Ruleset Information
---------------------------------
ipv4 Firewall "output filter"
Rule Action Protocol Packets Bytes
------- -------- ---------- --------- -------
default accept all 1 84
The Forward Chain
For the forward chain, we want it to be similar to the input chain. We want to deny everything by default, but allow anything to return that we initiated from the trusted side of our network.
set firewall ipv4 forward filter default-action drop
We’re going to put our rule allowing stateful traffic at rule 20, because we will need to put something before that in the next step.
set firewall ipv4 forward filter rule 20 action 'accept'
set firewall ipv4 forward filter rule 20 description 'Allow Return traffic through the router'
set firewall ipv4 forward filter rule 20 state 'established'
set firewall ipv4 forward filter rule 20 state 'related'
Just like with the input chain, we also need to scope the interface that the rule applies to.
set firewall ipv4 forward filter rule 20 inbound-interface name eth1
Using Flow Tables
nftables has a fastpath function called flow tables. We can use flowtables to bypass some steps in the filtering process provided we’ve already filtered some packets for the connection. This speeds up the overall forwarding of traffic when using the firewall.
We must first configure a flowtable. The name is arbitrary and can be anything (I call it FT1). We need to define what interface will have it’s traffic eligible for fast processing (eth1 for me), and finally we define whether our offload will be handled in software or hardware (“software” is perfectly fine if you’re not sure if your NIC supports hardware offload).
set firewall flowtable FT1 description 'Flow Table for the forward chain'
set firewall flowtable FT1 interface 'eth1'
set firewall flowtable FT1 offload 'software'
Next we need to create a rule for the offloaded traffic. We need an action of offload, which says to use fastpath for the rule. We also need to point it to the flowtable we just created.
set firewall ipv4 forward filter rule 10 action 'offload'
set firewall ipv4 forward filter rule 10 description 'Allow Return traffic through the router - Fast Path'
set firewall ipv4 forward filter rule 10 offload-target 'FT1'
set firewall ipv4 forward filter rule 10 state 'established'
set firewall ipv4 forward filter rule 10 state 'related'
You may have noticed that we didn’t put an inbound-interface for this rule. That’s because we will be using it for a number of interfaces later. Traffic isn’t allowed through this rule until it has already been filtered, so we can leave any specific interface off of it. This allows all interfaces to benefit from the offloading.
Here’s the full config for the forward chain.
admin@GK41# compare commands
set firewall ipv4 forward filter default-action 'drop'
set firewall ipv4 forward filter rule 10 action 'offload'
set firewall ipv4 forward filter rule 10 description 'Allow Return traffic through the router - Fast Path'
set firewall ipv4 forward filter rule 10 offload-target 'FT1'
set firewall ipv4 forward filter rule 10 state 'established'
set firewall ipv4 forward filter rule 10 state 'related'
set firewall ipv4 forward filter rule 20 action 'accept'
set firewall ipv4 forward filter rule 20 description 'Allow Return traffic through the router'
set firewall ipv4 forward filter rule 20 inbound-interface name 'eth1'
set firewall ipv4 forward filter rule 20 state 'established'
set firewall ipv4 forward filter rule 20 state 'related'
set firewall flowtable FT1 description 'Flow Table for the forward chain'
set firewall flowtable FT1 interface 'eth1'
set firewall flowtable FT1 offload 'software'
If everything looks good, we can commit this config.
admin@GK41# save
Warning: you have uncommitted changes that will not be saved.
admin@GK41# commit-confirm 5
commit-confirm will automatically reboot in 5 minutes unless changes
are confirmed.
Proceed ? [Y/n] y
Initialized commit-confirm; 5 minutes to confirm before reboot
admin@GK41# confirm
Reboot timer stopped
admin@GK41# save
We won’t have any forwarded traffic yet to verify. We’ll be doing more firewall configuration once we start adding our LAN connections.
Conclusion
That is all for Part 2. In Part 3, we will be adding our LAN connections to allow hosts to access the internet.
Video
A friend of mine has been turning these posts into videos on YouTube. Check it out:






Leave a Reply