FreeBSD gateway for Sky Fibre broadband (UK)

From Mann Systems
Jump to: navigation, search

This is a configuration for a FreeBSD system to serve as a gateway/router for Sky Fibre vDSL broadband.

Sky is one of a few UK ISPs that offers native IPv6.

Overview

The gateway will provide Internet access to the three LANs using both IPv4 and IPv6. It has two igb(4) interfaces, one of which will be used for the WAN connection to a Draytek Vigor 130 vDSL modem, and the other will be used for multiple LAN connections using VLANs.

The main software components needed are as follows:

WAN side:

Name Description Source
dhclient DHCPv4 client base
dhcp6 KAME DHCPv6 client and server packages
rtsold IPv6 router solicitation daemon base
openvpn VPN client/server packages

LAN side:

Name Description Source
isc-dhcpd DHCPv4/v6 server packages
rtadvd IPv6 router advertisement daemon base
unbound Recursive DNS resolver packages (older version in base doesn't support DNS-over-TLS)
nsd Authoritative DNS server packages
openntpd NTP server packages

Base system configuration

/etc/rc.conf

hostname="gateway.home.manncave.net"

# Rename interfaces more descriptively
ifconfig_igb0_name="lan0"
ifconfig_igb1_name="wan0"

# Create VLAN interfaces on lan0
vlans_lan0="vlan2 vlan3"
create_args_vlan2="vlan 2"
create_args_vlan3="vlan 3"

# lan0 configuration
ifconfig_lan0="inet 10.0.0.1/24"
ifconfig_lan0_ipv6="inet6 auto_linklocal"
ipv6_prefix_lan0="fded:c113:9176:0"

# vlan2 configuration
ifconfig_vlan2="inet 10.0.2.1/24"
ifconfig_vlan2_ipv6="inet6 auto_linklocal"
ipv6_prefix_vlan2="fded:c113:9176:2"

# vlan3 configuration
ifconfig_vlan3="inet 10.0.3.1/24"
ifconfig_vlan3_ipv6="inet6 auto_linklocal"
ipv6_prefix_vlan3="fded:c113:9176:3"

# wan0 configuration
ifconfig_wan0="DHCP"
ifconfig_wan0_ipv6="inet6 auto_linklocal"
ipv6_cpe_wanif="wan0"

gateway_enable="YES"
ipv6_gateway_enable="YES"

# Advertise IPv6 routers and prefixes on LAN interfaces
rtadvd_enable="YES"
rtadvd_interfaces="lan0 vlan2 vlan3"

# Create tun0 interface at boot so that pf rules can be applied to it                                   
cloned_interfaces="tun0"

pf_enable="YES"
pflog_enable="YES"

sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

sshd_enable="YES"

zfs_enable="YES"

keymap="uk"

/etc/dhclient.conf

interface "wan0" {
    send dhcp-client-identifier "skydsl";
    supersede domain-name-servers 1.1.1.1, 1.0.0.1;
}

Sky requires a dhcp-client-identifier option (DHCP option 61) to be sent in the request. This used to require a customer-specific string that you had to obtain from the Sky-supplied router but any arbitrary string seems to work now.

I also override the DNS servers provided in the DHCP response with [Cloudflare's public DNS servers https://en.wikipedia.org/wiki/1.1.1.1] instead.

/etc/pf.conf

#### Macros ####
ndp_icmp_types = "{ routersol, routeradv, neighbrsol, neighbradv, redir }"

tcp_services = "{ 22222 }"
udp_services = "{ openvpn }"


#### Tables ####
table <private> const { 10/8, 172.16/12, 192.168/16, 169.254/16, 127/8 }


#### Options ####
set block-policy drop
set loginterface wan0
set ruleset-optimization basic
set skip on { lo0, lan0, vlan2, tun0 }
set state-policy if-bound


#### Traffic Normalisation ####
scrub all fragment reassemble


#### Queueing ####


#### Translation ####

# NAT LAN subnets behind public IP
nat on wan0 inet from (lan0:network) to any -> (wan0)
nat on wan0 inet from (vlan2:network) to any -> (wan0)
nat on wan0 inet from (vlan3:network) to any -> (wan0)


#### Packet Filtering ####

# Default block rule
block log all label "Default block rule"

# Non-logging block rules
block in quick on wan0 inet proto udp from 0.0.0.0 to 255.255.255.255 port 4944 label "Reduce log noise from Draytek broadcasts"
block in quick on wan0 inet proto igmp from 192.168.2.1 to 224.0.0.1 label "Reduce log noise from Draytek multicasts"

# Block IPv4 link-local
block in quick inet from 169.254.0.0/16 to any label "Block IPv4 link-local"
block in quick inet from any to 169.254.0.0/16 label "Block IPv4 link-local"

# Block TCP/UDP port 0
block drop log quick inet proto tcp from any port = 0 to any label "Block traffic from port 0"
block drop log quick inet proto udp from any port = 0 to any label "Block traffic from port 0"
block drop log quick inet proto tcp from any to any port = 0 label "Block traffic to port 0"
block drop log quick inet proto udp from any to any port = 0 label "Block traffic to port 0"
block drop log quick inet6 proto tcp from any port = 0 to any label "Block traffic from port 0"
block drop log quick inet6 proto udp from any port = 0 to any label "Block traffic from port 0"
block drop log quick inet6 proto tcp from any to any port = 0 label "Block traffic to port 0"
block drop log quick inet6 proto udp from any to any port = 0 label "Block traffic to port 0"

# Allow guest hosts to talk to DHCP server
pass in quick on vlan3 inet proto udp from any port bootpc to 255.255.255.255 port bootps
pass in quick on vlan3 inet proto udp from any port bootpc to (vlan3) port bootps
pass out quick on vlan3 inet proto udp from (vlan3) port bootps to any port bootpc
# Restrict guest subnet from communicating with other subnets
pass in on vlan3 inet from (vlan3:network) to any
block in log on vlan3 inet from any to (lan0:network)
block in log on vlan3 inet from any to (vlan2:network)

# Don't allow packets from private networks to traverse WAN interface
#block drop log quick on wan0 inet from <private> to any

# Permit anything out from the firewall on any interface
pass out inet all flags S/SA keep state allow-opts label "Allow anything outbound from firewall on any interface"
pass out inet6 all flags S/SA keep state allow-opts label "Allow anything outbound from firewall on any interface"

# Permit important ICMP6 everywhere
pass quick inet6 proto ipv6-icmp all icmp6-type unreach keep state
pass quick inet6 proto ipv6-icmp all icmp6-type toobig keep state

# Allow IPv6 NDP ICMP types everywhere
pass quick inet6 proto ipv6-icmp from fe80::/10 to fe80::/10 icmp6-type $ndp_icmp_types keep state label "NDP from link-local to link-local"
pass quick inet6 proto ipv6-icmp from fe80::/10 to ff02::/16 icmp6-type $ndp_icmp_types keep state label "NDP from link-local to multicast link-local"
pass in quick inet6 proto ipv6-icmp from ff02::/16 to fe80::/10 icmp6-type $ndp_icmp_types keep state label "NDP inbound from multicast link-local to link-local"
pass in quick inet6 proto ipv6-icmp from :: to ff02::/16 icmp6-type $ndp_icmp_types keep state label "NDP inbound from undefined to multicast link-local"

# Permit inbound DHCP6 replies from link-local addresses
pass in quick on wan0 inet6 proto udp from fe80::/10 port = dhcpv6-server to fe80::/10 port = dhcpv6-client

# Permit inbound traffic on WAN for selected TCP services
pass in quick on wan0 inet proto tcp from any to (wan0) port $tcp_services flags S/SA keep state

# Permit inbound UDP to OpenVPN server
pass in quick on wan0 inet proto udp from any to (wan0) port $udp_services