FreeBSD is great operating system to be used as router, firewall, and VPN concentrator. When you install and configure FreeBSD router you should begin with standard FreeBSD server installation and configuration covered in another my blog post - Typical tasks after FreeBSD installation.
After typical FreeBSD server installation we can follow with configuration of other roles as
- Firewall and NAT
- WireGuard Site2site VPN tunneling
- Dynamic routing / OpenBGPD
- DNS
- DHCP
In this blog post, I will document various roles basic configurations.
Network and Loopback interfaces
In a router, you typically have more network interfaces. In addition to setting up physical network interfaces, it is a pretty good idea to also set a specific IP address on loopback interface, because you can reference the router in a better way then IP address of one specific network interface. Loopback interface sits inside the router between all other network interfaces. Loopback is typically a special IP address having network mask /32 (255.255.255.255), so the network subnet of a single device.
Let's assume we have following 5 physical network interface (vmx0, vmx1, vmx2, vmx3, vmx4, vmx5), 1 virtual network interface (wg0), and loopback interface (lo0). We would like to achieve following IP configuration:
Interface (WAN-1): vmx0 IP Addr: 10.100.6.254 Net Mask: 255.255.255.0
Interface (LAN-4): vmx1 IP Addr: 10.100.4.254 Net Mask: 255.255.255.0
Interface (VPN-1): wg0 IP Addr: 172.16.100.254 Net Mask: 255.255.255.0
The default Network Gateway (Default Router) is 10.100.6.1
Procedure to set network interfaces permanently (saved in /etc/rc.conf)
# Set IP on loopback
sysrc ifconfig_lo0_alias0="inet 10.100.0.1/32"
# set default router (default gateway)
sysrc defaultrouter="10.100.6.1"
Procedure to set network interfaces on running system
# Set IP settings on vmx0 interface
ifconfig vmx0 inet 10.100.6.254 netmask 255.255.255.0
# Set IP alias on loopback
ifconfig lo0 alias 10.100.0.1/32
# Show the current IP settings on vmx0 interface
ifconfig vmx0
# Show the current IP settings on loopback (lo0) interface
ifconfig lo0
# Show the current IP settings on all interfaces
ifconfig vmx0
Firewall and NAT
The firewall is a typical role on the router, because we usually want to secure our network zones (typically LAN segments). Another typical requirement in IPv4 networks is NAT (Network Address Translation).
In FreeBSD you can choose between IPFW (original FreeBSD firewall) and PF (firewall ported from OpenBSD) firewalls. Below is the typical configuration of IPFW firewall with NAT (SNAT/DNAT) feature ...
Procedure to configure IPFW firewall
sysrc firewall_enable="YES"
sysrc firewall_script="/etc/ipfw.rules" # the script file with Firewall rules
sysrc firewall_nat_enable="YES"
Firewall Script File /etc/ipfw.rules
# Define binaries
ipfw="/sbin/ipfw"
# Define interfaces
wan_if="vmx0"
# FLUSH EXISTING IPFW RULES
$ipfw -q -f flush
$ipfw -q nat flush
# DELETE EXISTING NAT RULES
$ipfw nat delete 1
# DNAT RULE
$ipfw nat 1 config if $wan_if redirect_port tcp 10.1.10.1:22 2222
# SNAT RULE
$ipfw add 50 nat 1 ip from any to any via $wan_if
# INIT FIREWALL RULES
$ipfw add 100 allow ip from any to any via lo0
$ipfw add 200 deny ip from any to 127.0.0.0/8
$ipfw add 300 deny ip from 127.0.0.0/8 to any
$ipfw add 400 deny ip from any to ::1
$ipfw add 500 deny ip from ::1 to any
$ipfw add 600 allow ipv6-icmp from :: to ff02::/16
$ipfw add 700 allow ipv6-icmp from fe80::/10 to fe80::/10
$ipfw add 800 allow ipv6-icmp from fe80::/10 to ff02::/16
$ipfw add 900 allow ipv6-icmp from any to any icmp6types 1
$ipfw add 1000 allow ipv6-icmp from any to any icmp6types 2,135,136
# CUSTOM ALLOW RULES STARTS HERE
$ipfw add 65000 allow ip from any to any
# EVERYTHING ELSE IS DENIED BY DEFAULT BY RULE 65535
# LET'S ADD ONE MORE DENY RULE, JUST IN CASE THE DEFAULT BEHAVIOR CHANGES
$ipfw add 65500 deny ip from any to any
Above firewall script allows every traffic because of rule 65000. If you want to implement zero trust between network segments, you should remove rule 65000 and allow only traffic you define.
Manual DNAT configuration management (it is not necessary, just for info)
# Show NAT Configuration
ipfw nat show config
# Add DNAT rule
ipfw nat 1 config if vmx0 redirect_port 10.1.10.1:22 2222
# Delete DNAT rule
ipfw nat delete 1
WireGuard Site2site VPN tunneling
I wrote another blog post about WireGuard installation and configuration - WireGuard VPN on FreeBSD.
Dynamic routing / OpenBGPD
You can run BGP on your router. In my homelabs I use openbgpd (port of BGP daemon from OpenBSD).
Let's assume we want following BGP configuration parameters.
LAN network 10.41.0.0/16
Installation and configuration procedures below work with BGP configuration parameters above. Change it appropriately to your particular environment.
Procedure to Install and Enable OpenBGPD
# Install OpenBGPD
pkg install -y openbgpd8
# Enable OpenBGPD
sysrc openbgpd_enable="YES"
Configure your BGP in configuration file /usr/local/etc/bgpd.conf
router-id 172.16.101.25
fib-update yes
neighbor 172.16.100.4 {
remote-as 65000
descr "wg-server-c4c"
}
# Announce local LAN
network 172.16.101.25/32
network 10.41.0.0/16
# Optional: accept everything
allow from any
allow to any
Procedure to Start BGP
service openbgpd start
Procedure to Restart BGP
# Restart BGP service
service openbgpd restart
Troubleshooting BGP
Show BGP neighbors.
root@r1:~ #bgpctl showNeighbor AS MsgRcvd MsgSent OutQ Up/Down State/PrfRcvd wg-server-c4c 65000 7 6 0 00:01:23 11 root@r1:~ #
Show Routing Information Base (RIB).
root@r1:~ #bgpctl show ribflags: * = Valid, > = Selected, I = via IBGP, A = Announced, S = Stale, E = Error, F = Filtered, L = Leaked origin validation state: N = not-found, V = valid, ! = invalid aspa validation state: ? = unknown, V = valid, ! = invalid origin: i = IGP, e = EGP, ? = Incomplete flags vs destination gateway lpref med aspath origin AI*> N-? 10.41.0.0/16 0.0.0.0 100 0 i *> N-? 10.200.0.0/16 172.16.100.4 100 0 65000 i *> N-? 172.16.100.0/31 172.16.100.4 100 0 65000 i *> N-? 172.16.100.2/31 172.16.100.4 100 0 65000 i *> N-? 172.16.100.4/31 172.16.100.4 100 0 65000 i *> N-? 172.16.101.1/32 172.16.100.4 100 0 65000 i *> N-? 172.16.101.11/32 172.16.100.4 100 0 65000 65020 i *> N-? 172.16.101.12/32 172.16.100.4 100 0 65000 65020 i AI*> N-? 172.16.101.25/32 0.0.0.0 100 0 i *> N-? 192.168.4.0/24 172.16.100.4 100 0 65000 65020 i *> N-? 192.168.5.0/24 172.16.100.4 100 0 65000 65020 i *> N-? 192.168.7.0/24 172.16.100.4 100 0 65000 65020 i *> N-? 192.168.8.0/24 172.16.100.4 100 0 65000 65020 i root@r1:~ #
Show Forwarding Information Base (FIB).
root@r1:~ #bgpctl show fibflags: B = BGP, C = Connected, S = Static N = BGP Nexthop reachable via this route r = reject route, b = blackhole route flags prio destinationgateway S 1 0.0.0.0/010.0.0.138 C 1 10.0.0.0/8link#5 C 1 10.0.0.0/24link#1 C 1 10.0.0.40/32link#3 C 1 10.41.4.0/24link#2 C 1 10.41.4.254/32link#3 B 19 10.200.0.0/16172.16.100.4 C 1 100.66.0.45/32link#4 C 1 100.85.205.94/32link#4 C 1 100.93.97.58/32link#4 C 1 100.96.56.81/32link#4 C 1 100.97.143.39/32link#4 C 1 100.100.100.100/32link#4 C 1 100.102.179.91/32link#4 C 1 100.108.60.51/32link#3 C 1 100.119.48.90/32link#4 C 1 127.0.0.1/32link#3 C 1 172.16.100.0/24link#5 B 19 172.16.100.0/31172.16.100.4 B 19 172.16.100.2/31172.16.100.4 CN 1 172.16.100.4/31link#5 B 19 172.16.100.4/31172.16.100.4 CN 1 172.16.100.5/32link#3 C 1 172.16.101.0/24link#5 B 19 172.16.101.1/32172.16.100.4 B 19 172.16.101.11/32172.16.100.4 B 19 172.16.101.12/32172.16.100.4 C 1 172.16.101.25/32link#3 C 1 192.168.0.0/16link#5 B 19 192.168.4.0/24172.16.100.4 B 19 192.168.5.0/24172.16.100.4 B 19 192.168.7.0/24172.16.100.4 B 19 192.168.8.0/24172.16.100.4 C r 1 ::/96link#3 C 1 ::1/128link#3 C r 1 ::ffff:0.0.0.0/96link#3 C 1 fd7a:115c:a1e0::/48link#4 C 1 fd7a:115c:a1e0::53/128 link#4 C 1 fd7a:115c:a1e0::d735:3c33/128 link#3 C r 1 fe80::/10 link#3 C 1 fe80::%lo0/64 link#3 C 1 fe80::1%lo0/128 link#3 C r 1 ff02::/16 link#3 root@r1:~ #
That's it. Your BGP should work.
DNS
You can run DNS on your FreeBSD router. In this blog post, I will show you DNS (BIND 9.20) Installation and Configuration.
Let's assume our Internal domain is home.uw.cz
Procedure to Install and Enable BIND Name Server
# Install Bind
pkg install -y bind920
# Enable Bind (named)
sysrc named_enable="YES"
# Start Bind (named) service
service named start
Edit configuration file /usr/local/etc/namedb/named.conf
options {
// All file and path names are relative to the chroot directory,
// if any, and should be fully qualified.
directory "/usr/local/etc/namedb/working";
pid-file "/var/run/named/pid";
dump-file "/var/dump/named_dump.db";
statistics-file "/var/stats/named.stats";
allow-query { any; };
allow-transfer { any; };
dnssec-validation no;
// If named is being used only as a local resolver, this is a safe default.
// For named to be accessible to the network, comment this option, specify
// the proper IP address, or delete this option.
listen-on { 127.0.0.1; 10.0.0.1; };
// If you have IPv6 enabled on this system, uncomment this option for
// use as a local resolver. To give access to the network, specify
// an IPv6 address, or the keyword "any".
// listen-on-v6 { ::1; };
// These zones are already covered by the empty zones listed below.
// If you remove the related empty zones below, comment these lines out.
disable-empty-zone "255.255.255.255.IN-ADDR.ARPA";
disable-empty-zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
disable-empty-zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
// If you've got a DNS server around at your upstream provider, enter
// its IP address here, and enable the line below. This will make you
// benefit from its cache, thus reduce overall DNS traffic in the Internet.
forwarders {
1.1.1.1; 8.8.8.8; 8.8.4.4;
};
// OTHER CONFIGURATION IS ABOVE …
type primary;
file "/usr/local/etc/namedb/primary/home.uw.cz.db";
};
Create zone file /usr/local/etc/namedb/primary/home.uw.cz.db
@ IN SOA ns1.int.msp.businesscloud.cz. hostmaster.int.msp.businesscloud.cz. (
2025110201 ; Serial number (YYYYMMDDnn)
3600 ; Refresh (1 hour)
900 ; Retry (15 minutes)
604800 ; Expire (1 week)
86400 ; Minimum TTL (1 day)
)
IN NS ns1.home.uw.cz.
; IN NS ns2.home.uw.cz.
; --- Host records ---
ns1 IN A 10.100.4.5
;ns2 IN A 10.100.4.6
jump-01 IN A 10.100.4.1
devops-01 IN A 10.100.4.10
thermostat-01 IN A 10.100.7.11
fve-01 IN A 10.100.7.21
server-01 IN A 10.1.8.11
server-02 IN A 10.1.8.12
Procedure to Reload Name Server configuration
# Reload Bind (named) service
service named reload
Procedure to Restart Name Server
# Restart Bind (named) service
service named restart
To use Internal Name Server, edit configuration file /etc/resolve.conf
search home.uw.cz
nameserver 10.1.10.254
That's it. Your name server should work now.
DHCP
You can run DHCP on your FreeBSD router. In this blog post, I will show you KEA Installation and Configuration.
Procedure to Install and Enable KEA DHCP Server
# Install KEA
pkg install -y kea
# Enable KEA (dhcpd)
kea_enable="YES"
kea_dhcp4_enable="YES"
# Start KEA service
service kea start
Edit configuration file /usr/local/etc/kea/kea-dhcp4.conf
"Dhcp4": {
"interfaces-config": {
"interfaces": [
"re1"
]
},
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/db/kea/dhcp4.leases"
},
"option-data": [
{
"name": "domain-search",
"data": "home.uw.cz"
},
{
"name": "domain-name-servers",
"data": "10.100.4.5"
}
],
"subnet4": [
{
"id": 1,
"subnet": "10.100.4.0/24",
"pools": [
{
"pool": "10.100.5.150 - 10.100.5.199"
}
],
"option-data": [
{
"name": "routers",
"data": "10.100.5.254"
}
]
}
]
"loggers": [
{
"name": "kea-dhcp4",
"output_options": [
{
"output": "/var/log/kea/kea-dhcp4.log",
"maxsize": 1048576,
"maxver": 3
}
],
"severity": "INFO",
"debuglevel": 0
}
]
}
}
Procedure to Reload DHCP Server configuration
# Reload KEA service
service kea reload
Procedure to Restart DHCP Server
# Restart KEA service
service kea restart
Conclusion
In this blog post we have covered typical roles you can use on your FreeBSD router. Hope you find this useful and in case of any trouble, do not hesitate to use comments to ask for further information or report any bug or misconfiguration in my configuration examples.
FreeBSD was the major router and server operating system on the Internet back in 1994 until early 2000' when Linux take somehow the dominance as the Internet Operating System. However, FreeBSD is in my opinion excellent operating system not only for network router and firewall. That's the reason why pfSense (2004 → present) and OPNsense (2015 → present) are very well known and used router and firewall appliances nowadays. Both of them are successors of m0n0wall (2003–2015).
OPNsense appliance is very good community project and it is a good solution for anyone without FreeBSD knowhow, however, if you are an IT-geek, you can use core FreeBSD to achieve what you want.
Enjoy.
No comments:
Post a Comment