Ubuntu 16.04 Full Stack Configuration (with Bonding Config): Difference between revisions
(→UPnP) |
(clean up, typos fixed: ie. → i.e. , controled → controlled, eg: → e.g.:) |
||
(8 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
<indicator name="Front">[[File:Menu-bonding.svg|link=:Category:Bonding|30px|Back up to the Bonding Page]]</indicator> |
|||
[[Category:Routers]] |
[[Category:Routers]] |
||
[[Category:Bonding Configuration]] |
|||
[[Category:3rd Party Routers]] |
[[Category:3rd Party Routers]] |
||
= Preface = |
= Preface = |
||
Line 80: | Line 83: | ||
linkname aa_wan1 |
linkname aa_wan1 |
||
Note the additional “unit” and “linkname” instructions from the linked guide, “unit” is in the index of the ppp connection created ( |
Note the additional “unit” and “linkname” instructions from the linked guide, “unit” is in the index of the ppp connection created (i.e. unit = 0 creates ppp0). |
||
=== /etc/ppp/chap-secrets === |
=== /etc/ppp/chap-secrets === |
||
Line 268: | Line 271: | ||
# Accept established connections from AAISP Line 2 (Bonding only) |
# Accept established connections from AAISP Line 2 (Bonding only) |
||
iptables -A INPUT -i pppoe-AA_2 -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT |
iptables -A INPUT -i pppoe-AA_2 -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT |
||
# Allow related traffic from AAISP Modem Stats 1 |
|||
# Reject anything else (not really needed as we will change default policy to drop later) |
|||
iptables -A INPUT - |
iptables -A INPUT -s 192.168.2.1/32 -i DEV_AA_WAN1_C -m state --state RELATED,ESTABLISHED -j ACCEPT |
||
# Allow related traffic from AAISP Modem Stats 2 (Bonding only) |
|||
iptables -A INPUT -s 192.168.3.1/32 -i DEV_AA_WAN1_C -m state --state RELATED,ESTABLISHED -j ACCEPT |
|||
# AAISP Line 1 MSS Clamping |
# AAISP Line 1 MSS Clamping |
||
iptables -A FORWARD -o pppoe-AA_1 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment -- |
iptables -A FORWARD -o pppoe-AA_1 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment -- |
||
Line 304: | Line 309: | ||
iptables -t nat -A POSTROUTING -o DEV_AA_WAN2_C -m comment --comment NAT -j MASQUERADE |
iptables -t nat -A POSTROUTING -o DEV_AA_WAN2_C -m comment --comment NAT -j MASQUERADE |
||
# Default drop everything from outside |
# Default drop everything from outside |
||
# Note that these drops are *important* because we don't reject any traffic in the rules themselves, without these, stuff will be wide open |
|||
iptables -P FORWARD DROP |
iptables -P FORWARD DROP |
||
iptables -P INPUT DROP |
iptables -P INPUT DROP |
||
Line 581: | Line 587: | ||
START_DAEMON=1 |
START_DAEMON=1 |
||
# Define here the external interface connected to the WAN ( |
# Define here the external interface connected to the WAN (e.g.: the public |
||
# IP address NIC) |
# IP address NIC) |
||
MiniUPnPd_EXTERNAL_INTERFACE="pppoe-AA_1" |
MiniUPnPd_EXTERNAL_INTERFACE="pppoe-AA_1" |
||
Line 587: | Line 593: | ||
# IP that the daemon should listen on. |
# IP that the daemon should listen on. |
||
# Note that you do *not* want this to be 0.0.0.0, as you don't want |
# Note that you do *not* want this to be 0.0.0.0, as you don't want |
||
# your MiniUPnPd to be |
# your MiniUPnPd to be controlled by anyone on the internet. |
||
MiniUPnPd_LISTENING_IP=”DEV_LAN” |
MiniUPnPd_LISTENING_IP=”DEV_LAN” |
||
Line 617: | Line 623: | ||
chmod 0755 /etc/ppp/ip-up.d/fix-upnp |
chmod 0755 /etc/ppp/ip-up.d/fix-upnp |
||
chmod +x /etc/ppp/ip-up.d/fix-upnp |
chmod +x /etc/ppp/ip-up.d/fix-upnp |
||
= Bonus: Run dslstats in Docker on Ubuntu = |
|||
I'll add this section because some people may find it useful if you either want dslstats for your own use directly or to submit to something like [https://www.mydslwebstats.co.uk/ MyDSLWebStats]. |
|||
== Install Docker == |
|||
Install Docker, we'll get a better version than what is in the normal repos: |
|||
apt-get install apt-transport-https ca-certificates curl software-properties-common |
|||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - |
|||
# Assuming amd64 |
|||
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |
|||
apt-get update |
|||
apt-get install docker-ce |
|||
== Download & Run Container == |
|||
Now we have docker, all we need to do is download and run the container, which can be done in a single command. This command will do the following: |
|||
* Names the container "dslstats_1" |
|||
* Opens a VNC server on 192.168.1.1:5900 (you should specifically set the router IP like I have to make sure it's only accessible privately) |
|||
* Opens a tcp listener on port 192.168.1.1:8080 - this won't actually do anything unless you enable the web server for dslstats |
|||
* Sets the password to login to VNC to "dslstats" |
|||
* Sets the path for the dslstats configurtion to be '''/etc/dslstats_1/''' on the '''host''' |
|||
* Mounts /etc/localtime from the host to use the correct timezone data |
|||
* Restarts the container as soon as the Docker daemon starts (should be on each reboot) |
|||
docker run -d \ |
|||
--name=dslstats_1 \ |
|||
-p 192.168.1.1:5900:5900 \ |
|||
-p 198.168.1.1:8080:8080 \ |
|||
-e "VNC_PASSWORD"="dslstats" |
|||
-v /etc/dslstats_1:/config \ |
|||
-v /etc/localtime:/etc/localtime:ro \ |
|||
--restart=always |
|||
rossallan/dslstats |
|||
Obviously if you are running 2 modems you wish to report stats for, you will need a second MyDSLWebStats account (if you are submitting there), and to modify this command for the second container to use different ports and configuration directory. |
|||
For more information about Docker installation, see [https://docs.docker.com/engine/installation/linux/ubuntu/#install-using-the-repository here], and for more information about the dslstats Docker container, see [https://hub.docker.com/r/rossallan/dslstats/ here]. |
|||
= Bonus: Port based policy routing to a third WAN = |
= Bonus: Port based policy routing to a third WAN = |
||
I also have a third WAN connection (provided by Virgin Media) over which I route some traffic based on the destination port. It’s of course possible to route it based on destination IP, source IP or any combination of routing rules you can think of. It’s also possible to use it as a failover if your PPP connection dies as well (although this guide does not cover this). |
|||
Coming soon. |
|||
Moving forward though I’ll be making assumptions that the third connection is a VM connection (or an “equivalent”) provided by DHCP. |
|||
== Configure Interface == |
|||
Edit /etc/network/interfaces and configure the interface for the connection, we give it a higher metric to make sure it doesn’t override any default routes we configured, we also provide a post-up script which we’ll cover later: |
|||
# VMEDIA |
|||
auto DEV_VM_WAN |
|||
iface DEV_VM_WAN inet dhcp |
|||
post-up /usr/local/sbin/fix_vm_policy |
|||
metric 100 |
|||
== Fix Firewalling == |
|||
We need to add some more iptables rules to allow this interface to NAT and receive related traffic etc., we won’t bother with IPv6 since we don’t get a v6 address: |
|||
iptables -A INPUT -i DEV_VM_WAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT |
|||
iptables -A FORWARD -i DEV_LAN -o DEV_VM_WAN -m comment --comment "Allow traffic from LAN -> internet" -j ACCEPT |
|||
iptables -A FORWARD -i DEV_VM_WAN -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from internet -> LAN" -j ACCEPT |
|||
iptables -t nat -A POSTROUTING -o DEV_VM_WAN -m comment --comment NAT -j MASQUERADE |
|||
Don’t forget '''netfilter-persistent save && netfilter-persistent reload''' afterwards. |
|||
== Fix Routing == |
|||
We need to add a new route table, it will be called VMEDIA. |
|||
echo “20 VMEDIA” >> /etc/iproute2/rt_tables |
|||
=== /usr/local/sbin/fix_vm_policy === |
|||
Create the script mentioned in post-up earlier. This script does the following: |
|||
* Fetch the interface address (a /32 IPv4 in this case) |
|||
* Fetch the gateway address |
|||
* Check these look like valid IP addresses to avoid any blank routes |
|||
* Add a default route via the gateway to the routing table VMEDIA |
|||
* Adds a rule to mark traffic from LAN with a destination port of 563 with mark 10 |
|||
* Adds a rule to source NAT traffic coming back on the interface to have the correct IP address (without this the external IP will not reply to pings for example) |
|||
* Adds a rule to send all traffic with mark 10 through the VMEDIA routing table |
|||
* Adds a rule to send all traffic destined for the /32 address associated with the connection through the VMEDIA routing table |
|||
* Flushes the route cache |
|||
* Loosens the return path filter on the interface in question |
|||
It’s important that you change the rule for port 563 to be your own rule(s) for policy routing. Notice that it is mentioned twice, the first checks if the rule exists, and the second actually adds the rule, so be sure to modify both. |
|||
#!/bin/bash |
|||
echo "IFACE: ${IFACE}" |
|||
echo "LOGICAL: ${LOGICAL}" |
|||
IFACE_ADDR=`ip addr show dev DEV_VM_WAN | grep "inet " | awk '{print $2}' | sed -E 's/\/[0-9]+$//'` |
|||
GWAY_ADDR=`ip route show dev DEV_VM_WAN | grep default | awk '{print $3}'` |
|||
(echo ${IFACE_ADDR} | grep -Eq "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") && echo "VM-FIX IFACE matched" || exit |
|||
(echo ${GWAY_ADDR} | grep -Eq "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") && echo "VM-FIX GWAY matched" || exit |
|||
ip route add default via ${GWAY_ADDR} dev DEV_VM_WAN table VMEDIA || true |
|||
IPT_CODE=`iptables -t mangle -C PREROUTING -p tcp --dport 563 -s 192.168.1.0/24 -j MARK --set-mark 10 2>&1 || true` |
|||
if [[ ! -z ${IPT_CODE// } ]]; then |
|||
echo "VM-FIX Adding rule 1" |
|||
iptables -t mangle -I PREROUTING 1 -p tcp --dport 563 -s 192.168.1.0/24 -j MARK --set-mark 10 || true |
|||
fi |
|||
IPT_CODE=`iptables -t nat -C POSTROUTING -o DEV_VM_WAN -j SNAT --to-source ${IFACE_ADDR} 2>&1 || true` |
|||
if [[ ! -z ${IPT_CODE// } ]]; then |
|||
echo "VM-FIX Adding rule 2" |
|||
iptables -t nat -I POSTROUTING 1 -o DEV_VM_WAN -j SNAT --to-source ${IFACE_ADDR} || true |
|||
fi |
|||
ip rule add fwmark 10 table VMEDIA || true |
|||
ip rule add from ${IFACE_ADDR}/32 table VMEDIA || true |
|||
ip route flush cache || true |
|||
if [ -f /proc/sys/net/ipv4/conf/DEV_VM_WAN/rp_filter ]; then |
|||
echo 2 > /proc/sys/net/ipv4/conf/DEV_VM_WAN/rp_filter |
|||
fi |
|||
Then: |
|||
chmod 0755 /usr/local/sbin/fix_vm_policy |
|||
chmod +x /usr/local/sbin/fix_vm_policy |
|||
You should now be able to bring up that interface and it should put all of its own routes in place. Traffic from the LAN should be routed appropriately. |
Latest revision as of 00:22, 18 August 2018
Preface
These instructions are for setting up Ubuntu 16.04 specifically with an AAISP PPPoE (VDSL & ADSL) connection, and a functioning LAN, with additional instructions for bonding, a third WAN with policy based routing, and additional LAN services such as DHCP(v6) and RADVD. The instructions will likely be similar for other versions of Ubuntu and Debian, but may require some changes. These instructions were built at least partly on:
- https://support.aa.net.uk/Router:Linux
- https://support.aa.net.uk/Router:Linux_-_Debian
- https://support.aa.net.uk/IPv6
- https://support.aa.net.uk/Linux_upload_bonding_using_teql
Initial System Setup
Make sure the system is up to date and install some essentials:
apt-get update apt-get upgrade -y apt-get install -y pppoe ppp iproute2 iptables ip6tables sed -i 's/#net\.ipv4\.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf sed -i 's/#net\.ipv6\.conf\.all\.forwarding=1/net.ipv6.conf.all.forwarding=1/' /etc/sysctl.conf sysctl -p
Networking Interface Information
This is going to vary for everyone depending on how your “router” is setup. I’ll be referring to various network interfaces in the guide, and I’ll use the names defined here to reference them, where they are used, these names refer to the physical name of the device. You need to replace them with your own interface names in applicable config sections.
Interface Name Used | Description |
---|---|
DEV_AA_WAN1 | Plugged into port marked LAN1 on HG612 for Line 1 (bridged connection used for PPPoE) |
DEV_AA_WAN1_C | Plugged into port marked LAN2 on HG612 for Line 1 (HG612 has a static IP of 192.168.2.1 and subnet mask 255.255.255.0), used for accessing modem stats |
DEV_AA_WAN2 | Plugged into port marked LAN1 on HG612 for Line 2 (bridged connection used for PPPoE) |
DEV_AA_WAN2_C | Plugged into port marked LAN2 on HG612 for Line 2 (HG612 has a static IP of 192.168.3.1 and subnet mask 255.255.255.0), used for accessing modem stats |
DEV_LAN | The interface on which the LAN is connected |
DEV_VM_WAN | Plugged into Virgin Media modem in bridge mode |
VLANs
Note that on Ubuntu, support for VLANs is not enabled by default, so if you are intending to use VLANs you will need to do the following:
modprobe 8021q echo "8021q" >> /etc/modules
You will then need to add your VLANs for use by doing:
vconfig add INTERFACE VLAN
For example:
vconfig add eth0 10
You can then use the notation eth0.10 to reference this interface with VLAN.
Setting Up PPP Connection(s)
A lot of this part of the guide can be seen here: https://support.aa.net.uk/Router:Linux_-_Debian#Setting_up_pppd
First Connection
/etc/ppp/peers/aaisp_wan1
Edit this file with the following (don’t forget to replace DEV_AA_WAN1 with your interface over which PPP should be dialled):
user your-line1-username plugin rp-pppoe.so DEV_AA_WAN1 noipdefault defaultroute hide-password lcp-echo-interval 1 lcp-echo-failure 10 noauth persist maxfail 0 mtu 1492 noaccomp default-asyncmap +ipv6 ipv6cp-use-ipaddr ifname pppoe-AA_1 unit 0 linkname aa_wan1
Note the additional “unit” and “linkname” instructions from the linked guide, “unit” is in the index of the ppp connection created (i.e. unit = 0 creates ppp0).
/etc/ppp/chap-secrets
Edit this file and input your username and password in the format specified below. If you have a second connection you can also add the credentials for this one while you are here:
# Secrets for authentication using CHAP # client server secret IP addresses line1-username * YourLine1Password line2-username * YourLine2Password
Testing
Test you get some sort of response directly:
pppoe -I DEV_AA_WAN1 -A
If you do, then the connection will probably succeed, try firing up the connection:
pon aaisp_wan1
It should connect and you should get a default IPv4 route. Now that we know it’s working we can disable it again:
poff aaisp_wan1
Second Connection (for Bonding)
Only do this if you have a second PPPoE connection with AAISP for use for bonding. Make sure that your primary IPv4 address is routed to both lines, and make sure an IPv6 /64 block is routed to both lines. Multiple IPv4 addresses and IPv6 blocks are outside the scope of this guide.
/etc/ppp/peers/aaisp_wan2
Edit the file as shown for aaisp_wan1 but importantly, make sure the device is set to your DEV_AA_WAN2, and change the “ifname”, “unit” and “linkname” directives.
Testing
Again, you can test in the same way as with aaisp_wan1.
Further Config Changes
For bonding, it’s important now to go into both config files (/etc/ppp/peers/aaisp_wan1 & /etc/ppp/peers/aaisp_wan2), and to comment out the “defaultroute” directive. We don’t want either of these connections to become default routes as we will implement the bonding with a virtual interface later on.
Configuring Network Interfaces
Time to do some work on the network interfaces themselves, fire up your favourite text editor and edit the file /etc/network/interfaces
Most likely it’s populated with something like the following already:
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback auto enp0s20f0 iface enp0s20f0 inet dhcp
You’ll need to make sure that as you edit this file, you don’t define any interfaces a second time.
VLANs
Another note on VLANs, whenever you use one, you should always specify “vlan-raw-device” inside the interface definition, and there should always be a “manual” definition for the raw device itself as well. For example, assuming we have eth4, and the modem stats port is connected on VLAN 20, the definition would look like this:
auto eth4 iface eth4 inet manual auto eth4.20 iface eth4.20 inet static vlan-raw-device eth4 address 192.168.2.2 netmask 255.255.255.0
You also need to make sure you have added this interface with vconfig as mentioned further up in the guide.
LAN
Firstly let’s define your LAN interface, this is where DHCP will operate and your LAN clients are connected to. Make sure to replace DEV_LAN with your physical device.
I’m using 192.168.1.0/24 as my LAN but feel free to use whatever you want.
For IPv6, assign the first address of your routed /64 block, so if your block is 2001:db8:b9:2041::/64, then assign 2001:db8:b9:2041::1.
# LAN Configuration auto DEV_LAN iface DEV_LAN inet static address 192.168.1.1 netmask 255.255.255.0 iface DEV_LAN inet6 static address 2001:db8:b9:2041::1 netmask 64
First Connection
We need to make 2 entries in the file for the connection, one for the physical interface itself and one to actually bring up PPP:
# AAISP WAN1 auto DEV_AA_WAN1 iface DEV_AA_WAN1 inet manual # AAISP PPPoE 1 auto aa_wan1 iface aa_wan1 inet ppp pre-up /sbin/ip link set DEV_AA_WAN1 up provider aaisp_wan1
I am not sure the pre-up is strictly necessary but it seems to have helped for me.
Control Interface
If you have an HG612 with the IPs statically configured like I described, then you can also configure the modem stats interface:
# AAISP Modem Stats 1 auto DEV_AA_WAN1_C iface DEV_AA_WAN1_C inet static address 192.168.2.2 netmask 255.255.255.0
Second Connection (for Bonding)
Configure this exactly as described in “First Connection” but with the correct interfaces and provider name.
Testing
In theory now you can “ifup” all of the interfaces you just configured. The PPP interfaces should connect and get both an IPv4 address and an IPv6 link-local address.
If you are not bonding, a default IPv4 route should have been added and connectivity should work. You should also be able to statically assign yourself an IP address in the range you specified for LAN, connect on that interface and the router should respond to ping.
Fixing Routes
One Connection Only
If you are not bonding, then you should already get a default IPv4 route, and we simply need to make it so that an appropriate IPv6 route is added when the PPP interface comes up.
Create a new file /etc/ppp/ipv6-up.d/set-route with the following:
/sbin/ip -6 route add default dev $1
Then execute:
chmod 0755 /etc/ppp/ipv6-up.d/set-route chmod +x /etc/ppp/ipv6-up.d/set-route
If you “ifdown” and “ifup” the interface, you should get an IPv6 default route now. You can check with “ip -6 route”.
Two (or more) Connections Bonded
If bonding, we need to enable the teql scheduler and set up some scripts to fix routing and bonding.
Enable the Scheduler
modprobe sch_teql echo "sch_teql" >> /etc/modules
Fixing the Routing
Create a new file /etc/ppp/ip-up.d/fix-teql with the following contents (make sure to put in your IPv4 & first IPv6 address):
#!/bin/bash /sbin/sysctl -w net.ipv4.conf.pppoe-AA_1.rp_filter=2 /sbin/sysctl -w net.ipv4.conf.pppoe-AA_2.rp_filter=2 /sbin/tc qdisc add dev pppoe-AA_1 root teql0 /sbin/tc qdisc add dev pppoe-AA_2 root teql0 /sbin/ip address add YOUR_IPV4_ADDRESS/32 dev teql0 /sbin/ip address add YOUR_FIRST_IPV6_ADDRESS/64 dev teql0 /sbin/ip link set teql0 up /sbin/ip route replace default scope global dev teql0 /sbin/ip -6 route replace default scope global dev teql0
Then execute:
chmod 0755 /etc/ppp/ip-up.d/fix-teql chmod +x /etc/ppp/ip-up.d/fix-teql
At this time, if your PPP connections are up from previous testing, you can manually run this script, and you should then get connectivity on both IPv4 & IPv6. You can also check “ip route” and “ip -6 route” and the teql0 device should be the default route for both.
Firewalling
You can use iptables to configure a firewall for your system and also to apply some features such as IPv4 NAT for LAN.
The rules are mostly taken from https://support.aa.net.uk/Router:Linux_-_Debian#Configuring_your_firewall and are commented so you can execute what you need. Also remember to replace your devices as before (although the PPP devices are named correctly if you followed the guide.
IPv4 Rules
Note that implementing these rules wipes your existing IPv4 rules if you have any.
# Wipe all existing rules iptables -t filter -F iptables -t nat -F iptables -t mangle -F iptables -t filter -X iptables -t nat -X iptables -t mangle -X # Accept everything from localhost iptables -A INPUT -i lo -m comment --comment "Accept all from localhost" -j ACCEPT # Accept all ICMP iptables -A INPUT -p icmp -m comment --comment "Accept all ICMP" -j ACCEPT # Accept everything from LAN iptables -A INPUT -i DEV_LAN -m comment --comment "Accept all from the LAN" -j ACCEPT # Accept established connections from AAISP Line 1 iptables -A INPUT -i pppoe-AA_1 -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT # Accept established connections from AAISP Line 2 (Bonding only) iptables -A INPUT -i pppoe-AA_2 -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT # Allow related traffic from AAISP Modem Stats 1 iptables -A INPUT -s 192.168.2.1/32 -i DEV_AA_WAN1_C -m state --state RELATED,ESTABLISHED -j ACCEPT # Allow related traffic from AAISP Modem Stats 2 (Bonding only) iptables -A INPUT -s 192.168.3.1/32 -i DEV_AA_WAN1_C -m state --state RELATED,ESTABLISHED -j ACCEPT # AAISP Line 1 MSS Clamping iptables -A FORWARD -o pppoe-AA_1 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment -- comment "Clamp MSS for traffic going via PPP" -j TCPMSS --clamp-mss-to-pmtu # AAISP Line 2 MSS Clamping (Bonding only) iptables -A FORWARD -o pppoe-AA_2 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "Clamp MSS for traffic going via PPP" -j TCPMSS --clamp-mss-to-pmtu # Allow traffic from LAN to AAISP Line 1 iptables -A FORWARD -i DEV_LAN -o pppoe-AA_1 -m comment --comment "Allow traffic from LAN -> internet" -j ACCEPT # Allow traffic from LAN to AAISP Line 2 (Bonding only) iptables -A FORWARD -i DEV_LAN -o pppoe-AA_2 -m comment --comment "Allow traffic from LAN -> internet" -j ACCEPT # Allow traffic from LAN to teql0 Bond (Bonding only) iptables -A FORWARD -i DEV_LAN -o teql0 -m comment --comment "Allow traffic from LAN -> internet" -j ACCEPT # Allow related traffic from AAISP Line 1 to LAN iptables -A FORWARD -i pppoe-AA_1 -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from internet -> LAN" -j ACCEPT # Allow related traffic from AAISP Line 2 to LAN (Bonding only) iptables -A FORWARD -i pppoe-AA_2 -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from internet -> LAN" -j ACCEPT # Allow traffic from LAN to AAISP Modem Stats 1 iptables -A FORWARD -i DEV_LAN -o DEV_AA_WAN1_C -m comment --comment "Allow traffic from LAN -> Control" -j ACCEPT # Allow related traffic back from AAISP Modem Stats 1 to LAN iptables -A FORWARD -I DEV_AA_WAN1_C -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from Control -> LAN" -j ACCEPT # Allow traffic from LAN to AAISP Modem Stats 2 (Bonding only) iptables -A FORWARD -i DEV_LAN -o DEV_AA_WAN2_C -m comment --comment "Allow traffic from LAN -> Control" -j ACCEPT # Allow related traffic back from AAISP Modem Stats 2 to LAN (Bonding only) iptables -A FORWARD -I DEV_AA_WAN2_C -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from Control -> LAN" -j ACCEPT # Allow NAT on AAISP Line 1 iptables -t nat -A POSTROUTING -o pppoe-AA_1 -m comment --comment NAT -j MASQUERADE # Allow NAT on AAISP Line 2 (Bonding only) iptables -t nat -A POSTROUTING -o pppoe-AA_2 -m comment --comment NAT -j MASQUERADE # Allow NAT on teql0 Bond (not sure this is necessary) (Bonding only) iptables -t nat -A POSTROUTING -o teql0 -m comment --comment NAT -j MASQUERADE # Allow NAT to get to AAISP Mode Stats Line 1 iptables -t nat -A POSTROUTING -o DEV_AA_WAN1_C -m comment --comment NAT -j MASQUERADE # Allow NAT to get to AAISP Mode Stats Line 2 (Bonding only) iptables -t nat -A POSTROUTING -o DEV_AA_WAN2_C -m comment --comment NAT -j MASQUERADE # Default drop everything from outside # Note that these drops are *important* because we don't reject any traffic in the rules themselves, without these, stuff will be wide open iptables -P FORWARD DROP iptables -P INPUT DROP iptables -P OUTPUT ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT
IPv6 Rules
Note that implementing these rules wipes your existing IPv6 rules if you have any.
# Wipe all existing rules ip6tables -F ip6tables -X # Accept everything from localhost ip6tables -A INPUT -i lo -m comment --comment "Accept all from localhost" -j ACCEPT # Accept all ICMP ip6tables -A INPUT -p ipv6-icmp -m comment --comment "Accept all ICMP" -j ACCEPT # Accept everything from LAN ip6tables -A INPUT -i DEV_LAN -m comment --comment "Accept all from LAN" -j ACCEPT # Accept established connections from AAISP Line 1 ip6tables -A INPUT -i pppoe-AA_1 -m state --state RELATED,ESTABLISHED -m comment --comment "Accept related & return traffic" -j ACCEPT # Accept established connections from AAISP Line 2 (Bonding only) ip6tables -A INPUT -i pppoe-AA_2 -m state --state RELATED,ESTABLISHED -m comment --comment "Accept related & return traffic" -j ACCEPT # Forward all ICMP ip6tables -A FORWARD -p ipv6-icmp -m comment --comment "Forward all ICMP" -j ACCEPT # Allow traffic from LAN to AAISP Line 1 ip6tables -A FORWARD -i DEV_LAN -o pppoe-AA_1 -m comment --comment "Allow LAN -> internet" -j ACCEPT # Allow traffic from LAN to AAISP Line 2 (Bonding only) ip6tables -A FORWARD -i DEV_LAN -o pppoe-AA_2 -m comment --comment "Allow LAN -> internet" -j ACCEPT # Allow traffic from LAN to teql0 Bond (Bonding only) ip6tables -A FORWARD -i DEV_LAN -o teql0 -m comment --comment "Allow LAN -> internet" -j ACCEPT # Allow related traffic from AAISP Line 1 to LAN ip6tables -A FORWARD -i pppoe-AA_1 -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow related & return traffic WAN -> LAN" -j ACCEPT # Allow related traffic from AAISP Line 2 to LAN (Bonding only) ip6tables -A FORWARD -i pppoe-AA_2 -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow related & return traffic WAN -> LAN" -j ACCEPT # Default drop everything from outside ip6tables -P FORWARD DROP ip6tables -P INPUT DROP ip6tables -P OUTPUT ACCEPT
Testing
You should now be able to statically assign a computer an address in your LAN subnet, connect to the LAN port on this router and you should have IPv4 connectivity to the internet at least at this point. If you wish you can also test IPv6 in this way by assigning an address from your block.
Final Steps
We now need to install iptables-persistent to save the rules across reboots:
apt-get install iptables-persistent
In the prompts select that you wish to save the rules now. Note that if you change rules manually in the future you will need to issue the following command to persist them (but note that it will also persist any rules added for things like UPnP):
netfilter-persistent save netfilter-persistent reload
LAN Setup
This section deals with setting up services for your LAN network. We will cover the following:
- BIND (DNS Forwarder with Caching)
- DHCP
- DHCPv6
- RADVD
- UPnP
BIND (DNS)
BIND is relatively simple to setup in this way, firstly install it:
apt-get install bind9
Now edit the file /etc/bind/named.conf.options and update it with the following. Note that you should replace 192.168.1.1 with the statically assigned IPv4 address on your LAN interface, and 2001:db8:b9:2041::1 with the statically assigned IPv6 address on your LAN.
acl goodclients { 191.168.1.0/24; localhost; localnets; }; options { directory "/var/cache/bind"; recursion yes; allow-query { goodclients; }; # Feel free to add your own DNS servers here forwarders { 8.8.8.8; 8.8.4.4; }; dnssec-enable yes; dnssec-validation yes; auth-nxdomain no; listen-on-v6 { 2001:db8:b9:2041::1; ::1; }; listen-on { 192.168.1.1; 127.0.0.1; }; };
Issue:
systemctl enable bind9 systemctl restart bind9
It should now be possible to issue DNS requests to the local system:
root@ubuntu-router:/# dig +noauthority aaisp.net A @127.0.0.1 ; <<>> DiG 9.10.3-P4-Ubuntu <<>> +noauthority aaisp.net A @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54288 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;aaisp.net. IN A ;; ANSWER SECTION: aaisp.net. 3420 IN A 81.187.30.81 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed May 03 14:54:36 BST 2017 ;; MSG SIZE rcvd: 262
If you would like to force the local machine to use this caching server for lookups, but not change /etc/network/interfaces to do so, and also avoid messing with resolvconf, you can do the following, although it’s not the recommended method for doing so:
echo “nameserver 127.0.0.1” >> /etc/resolvconf/resolv.conf.d/head
DHCP
DHCP is relatively easy to setup for IPv4 but is going to require some manual tweaks for IPv6 (listed in the next section).
Install the ISC DHCP Server:
apt-get install isc-dhcp-server
Edit /etc/default/isc-dhcp-server and edit INTERFACES to add your LAN interface:
# Defaults for isc-dhcp-server initscript # sourced by /etc/init.d/isc-dhcp-server # installed at /etc/default/isc-dhcp-server by the maintainer scripts # # This is a POSIX shell fragment # # Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf). #DHCPD_CONF=/etc/dhcp/dhcpd.conf # Path to dhcpd's PID file (default: /var/run/dhcpd.pid). #DHCPD_PID=/var/run/dhcpd.pid # Additional options to start dhcpd with. # Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead #OPTIONS="" # On what interfaces should the DHCP server (dhcpd) serve DHCP requests? # Separate multiple interfaces with spaces, e.g. "eth0 eth1". INTERFACES="DEV_LAN"
Now you can edit /etc/dhcp/dhcpd.conf and update it for your use, a sample config is shown below:
ddns-update-style none; default-lease-time 600; max-lease-time 7200; log-facility local7; subnet 192.168.1.0 netmask 255.255.255.0 { range 192.168.1.50 192.168.1.200; option routers 192.168.1.1; option domain-name-servers 192.168.1.1; option broadcast-address 192.168.1.255; }
Once that’s done, you can issue the following:
systemctl enable isc-dhcp-server systemctl restart isc-dhcp-server
This should give you working DHCP for IPv4 on your LAN.
DHCPv6
DHCPv6 is supported by isc-dhcp-server but requires us to make a new init script and change some configuration (credit: https://www.interlan.se/fix-isc-dhcp-server6-ubuntu-16-04/ ). I will assume you already did the DHCP setup mentioned previously.
Execute:
cp /etc/default/isc-dhcp-server /etc/default/isc-dhcp-server6
Edit /etc/default/isc-dhcp-server6 and change the options as follows:
# Defaults for isc-dhcp-server initscript # sourced by /etc/init.d/isc-dhcp-server # installed at /etc/default/isc-dhcp-server by the maintainer scripts # # This is a POSIX shell fragment # # Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf). DHCPD_CONF=/etc/dhcp/dhcpd6.conf # Path to dhcpd's PID file (default: /var/run/dhcpd.pid). DHCPD_PID=/var/run/dhcpd6.pid # Additional options to start dhcpd with. # Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead OPTIONS="-6" # On what interfaces should the DHCP server (dhcpd) serve DHCP requests? # Separate multiple interfaces with spaces, e.g. "eth0 eth1". INTERFACES="DEV_LAN"
Edit /etc/dhcp/dhcpd6.conf and populate it with your /64 block and a suitable range, a sample config is:
default-lease-time 2592000; preferred-lifetime 604800; option dhcp-renewal-time 3600; option dhcp-rebinding-time 7200; allow leasequery; option dhcp6.name-servers 2001:db8:b9:2041::1; option dhcp6.info-refresh-time 21600; subnet6 2001:db8:b9:2041::/64 { range6 2001:db8:b9:2041::100 2001:db8:b9:2041:ffff:ffff:ffff:ffff; range6 2001:db8:b9:2041::/64 temporary; }
Execute:
cp /etc/init.d/isc-dhcp-server /etc/init.d/isc-dhcp-server6 sed -i s/isc-dhcp-server/isc-dhcp-server6/ /etc/init.d/isc-dhcp-server6 sed -i s/dhcpd.conf/dhcpd6.conf/ /etc/init.d/isc-dhcp-server6 sed -i s/dhcpd.pid/dhcpd6.pid/ /etc/init.d/isc-dhcp-server6 systemctl enable isc-dhcp-server6 systemctl start isc-dhcp-server6
You should now get an IPv6 address, although you may not, and if you do, depending on the OS, it may not actually work properly until you’ve gone to the next section and setup RADVD.
RADVD
RADVD config is actually very easy with a simple config. Just install RADVD first:
apt-get install radvd
Then edit /etc/radvd.conf and update it with your interface and prefix, here is a sample config:
interface DEV_LAN { AdvSendAdvert on; prefix 2001:db8:b9:2041::/64 { AdvOnLink on; AdvAutonomous on; }; };
Once done, execute:
systemctl enable radvd systemctl restart radvd
This should give your LAN clients IPv6 addresses and connectivity.
UPnP
UPnP is something I do have working, but for me it can be a little temperamental after a reboot, but usually starts working after a couple of minutes.
We will use miniupnpd for this, and the configuration options are really quite minimal.
Firstly, install miniupnpd:
apt-get install miniupnpd
Next, edit /etc/default/miniupnpd and update it as follows (notice the commenting out of the OTHER_OPTIONS”). If you need UPnP for IPv6, don’t forget to also set the last option to “yes”:
# Set to 1 to start the daemon. Desactivated by default, because # you don't want the outside to control your UPnP router, and # as a consequence MiniUPnPd_LISTENING_IP should be set to a # reasonable value before enabling the daemon. START_DAEMON=1 # Define here the external interface connected to the WAN (e.g.: the public # IP address NIC) MiniUPnPd_EXTERNAL_INTERFACE="pppoe-AA_1" # IP that the daemon should listen on. # Note that you do *not* want this to be 0.0.0.0, as you don't want # your MiniUPnPd to be controlled by anyone on the internet. MiniUPnPd_LISTENING_IP=”DEV_LAN” # This defines other options which you might want to use when # starting MiniUPnPd. Note that the -S option is important: # -S sets "secure" mode : clients can only add mappings to their own ip # (see man page) #MiniUPnPd_OTHER_OPTIONS="-N -f /etc/miniupnpd/miniupnpd.conf" MiniUPnPd_OTHER_OPTIONS="" # If this option is defined, then the init script will initialize # the ipv6 tables. MiniUPnPd_ip6tables_enable=no
Once that’s done, you should be able to execute:
systemctl enable miniupnpd systemctl start miniupnpd
We need to also restart miniupnpd when a PPP interface comes up or down. If we don’t do this, then miniupnpd will usually start at boot time before the PPP interface is connected, and this breaks the rules it puts in place.
Create a new file /etc/ppp/ip-up.d/fix-upnp with the following contents:
#!/bin/bash /etc/init.d/miniupnpd restart
Then execute:
chmod 0755 /etc/ppp/ip-up.d/fix-upnp chmod +x /etc/ppp/ip-up.d/fix-upnp
Bonus: Run dslstats in Docker on Ubuntu
I'll add this section because some people may find it useful if you either want dslstats for your own use directly or to submit to something like MyDSLWebStats.
Install Docker
Install Docker, we'll get a better version than what is in the normal repos:
apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # Assuming amd64 add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" apt-get update apt-get install docker-ce
Download & Run Container
Now we have docker, all we need to do is download and run the container, which can be done in a single command. This command will do the following:
- Names the container "dslstats_1"
- Opens a VNC server on 192.168.1.1:5900 (you should specifically set the router IP like I have to make sure it's only accessible privately)
- Opens a tcp listener on port 192.168.1.1:8080 - this won't actually do anything unless you enable the web server for dslstats
- Sets the password to login to VNC to "dslstats"
- Sets the path for the dslstats configurtion to be /etc/dslstats_1/ on the host
- Mounts /etc/localtime from the host to use the correct timezone data
- Restarts the container as soon as the Docker daemon starts (should be on each reboot)
docker run -d \ --name=dslstats_1 \ -p 192.168.1.1:5900:5900 \ -p 198.168.1.1:8080:8080 \ -e "VNC_PASSWORD"="dslstats" -v /etc/dslstats_1:/config \ -v /etc/localtime:/etc/localtime:ro \ --restart=always rossallan/dslstats
Obviously if you are running 2 modems you wish to report stats for, you will need a second MyDSLWebStats account (if you are submitting there), and to modify this command for the second container to use different ports and configuration directory.
For more information about Docker installation, see here, and for more information about the dslstats Docker container, see here.
Bonus: Port based policy routing to a third WAN
I also have a third WAN connection (provided by Virgin Media) over which I route some traffic based on the destination port. It’s of course possible to route it based on destination IP, source IP or any combination of routing rules you can think of. It’s also possible to use it as a failover if your PPP connection dies as well (although this guide does not cover this).
Moving forward though I’ll be making assumptions that the third connection is a VM connection (or an “equivalent”) provided by DHCP.
Configure Interface
Edit /etc/network/interfaces and configure the interface for the connection, we give it a higher metric to make sure it doesn’t override any default routes we configured, we also provide a post-up script which we’ll cover later:
# VMEDIA auto DEV_VM_WAN iface DEV_VM_WAN inet dhcp post-up /usr/local/sbin/fix_vm_policy metric 100
Fix Firewalling
We need to add some more iptables rules to allow this interface to NAT and receive related traffic etc., we won’t bother with IPv6 since we don’t get a v6 address:
iptables -A INPUT -i DEV_VM_WAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic" -j ACCEPT iptables -A FORWARD -i DEV_LAN -o DEV_VM_WAN -m comment --comment "Allow traffic from LAN -> internet" -j ACCEPT iptables -A FORWARD -i DEV_VM_WAN -o DEV_LAN -m state --state RELATED,ESTABLISHED -m comment --comment "Allow return traffic from internet -> LAN" -j ACCEPT iptables -t nat -A POSTROUTING -o DEV_VM_WAN -m comment --comment NAT -j MASQUERADE
Don’t forget netfilter-persistent save && netfilter-persistent reload afterwards.
Fix Routing
We need to add a new route table, it will be called VMEDIA.
echo “20 VMEDIA” >> /etc/iproute2/rt_tables
/usr/local/sbin/fix_vm_policy
Create the script mentioned in post-up earlier. This script does the following:
- Fetch the interface address (a /32 IPv4 in this case)
- Fetch the gateway address
- Check these look like valid IP addresses to avoid any blank routes
- Add a default route via the gateway to the routing table VMEDIA
- Adds a rule to mark traffic from LAN with a destination port of 563 with mark 10
- Adds a rule to source NAT traffic coming back on the interface to have the correct IP address (without this the external IP will not reply to pings for example)
- Adds a rule to send all traffic with mark 10 through the VMEDIA routing table
- Adds a rule to send all traffic destined for the /32 address associated with the connection through the VMEDIA routing table
- Flushes the route cache
- Loosens the return path filter on the interface in question
It’s important that you change the rule for port 563 to be your own rule(s) for policy routing. Notice that it is mentioned twice, the first checks if the rule exists, and the second actually adds the rule, so be sure to modify both.
#!/bin/bash echo "IFACE: ${IFACE}" echo "LOGICAL: ${LOGICAL}" IFACE_ADDR=`ip addr show dev DEV_VM_WAN | grep "inet " | awk '{print $2}' | sed -E 's/\/[0-9]+$//'` GWAY_ADDR=`ip route show dev DEV_VM_WAN | grep default | awk '{print $3}'` (echo ${IFACE_ADDR} | grep -Eq "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") && echo "VM-FIX IFACE matched" || exit (echo ${GWAY_ADDR} | grep -Eq "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") && echo "VM-FIX GWAY matched" || exit ip route add default via ${GWAY_ADDR} dev DEV_VM_WAN table VMEDIA || true IPT_CODE=`iptables -t mangle -C PREROUTING -p tcp --dport 563 -s 192.168.1.0/24 -j MARK --set-mark 10 2>&1 || true` if [[ ! -z ${IPT_CODE// } ]]; then echo "VM-FIX Adding rule 1" iptables -t mangle -I PREROUTING 1 -p tcp --dport 563 -s 192.168.1.0/24 -j MARK --set-mark 10 || true fi IPT_CODE=`iptables -t nat -C POSTROUTING -o DEV_VM_WAN -j SNAT --to-source ${IFACE_ADDR} 2>&1 || true` if [[ ! -z ${IPT_CODE// } ]]; then echo "VM-FIX Adding rule 2" iptables -t nat -I POSTROUTING 1 -o DEV_VM_WAN -j SNAT --to-source ${IFACE_ADDR} || true fi ip rule add fwmark 10 table VMEDIA || true ip rule add from ${IFACE_ADDR}/32 table VMEDIA || true ip route flush cache || true if [ -f /proc/sys/net/ipv4/conf/DEV_VM_WAN/rp_filter ]; then echo 2 > /proc/sys/net/ipv4/conf/DEV_VM_WAN/rp_filter fi
Then:
chmod 0755 /usr/local/sbin/fix_vm_policy chmod +x /usr/local/sbin/fix_vm_policy
You should now be able to bring up that interface and it should put all of its own routes in place. Traffic from the LAN should be routed appropriately.