Using PPPoE from a FreeBSD 6.0 server to access iiNet
Grenville Armitage
January 3rd 2008


I've had broadband access with iiNet since January 2006, using their recommended Belkin 4-port ADSL router + VoIP adaptor (F1PI241ENau). The Belkin box NAT'd traffic between my home LAN and a PPPoE connection to iiNet while also providing VoIP ATA functionality to my home Asterisk server. In August 2007 I migrated the PPPoE termination, firewalling and NAT functionality to a FreeBSD box on the home LAN.
This documentation is largely for my own benefit - a record of what I did in case I ever need to do it again. With any luck, this information will be useful to others (like you, if you're reading this page and you aren't me).

An overview of the situation

There are four main components of my home setup:
As of August 2007 the server at 10.1.1.3 now terminates the PPPoE connection to iiNet and is the default gateway to 'the internet' for all other hosts on my LAN. The Belkin's internal 4-port Ethernet switch ports provide connectivity between a number of hosts on my home LAN, including 10.1.1.3. The FreeBSD server's Ethernet port xl0 carries PPPoE frames to and from iiNet via the Belkin ADSL modem, and also carries native IPv4 over Ethernet frames when communicating with other hosts on my 10.1.1/24 home LAN. An entirely separate LAN hangs off the FreeBSD server's fxp0 interface (10.1.2/24) for isolated media boxes.

Configuring PPPoE from the FreeBSD 6.0 server

The server at 10.1.1.3 required configuration of PPPoE service information, rc.conf changes to ensure ppp starts up at boot time, and  ppp.linkup entry to trigger dynamic DNS updates whenever the PPPoE link comes up.


Setting up PPPoE to iiNet

The following entry must be added to
/etc/ppp/ppp.conf to enable PPPoE connections to iiNet. Note the 'set device' line -  the FreeBSD server's xl0 interface is connected to one of the Belkin's 4 LAN ports, and is the path over which PPPoE frames will be exchanged with iiNet's PPPoE server.

#############
iinet:
 #
 # first, allow us to control the ppp session using
 # 'pppctl /var/run/ppp/iinet' at a later stage
 #
 set server /var/run/ppp/iinet "" 0177
 #
 # Reset logging so we don't see LCP messages associated
 # with Echo packets every 10 seconds (see later settings)
 set log Phase IPCP CCP tun command
 #
 # Set PPPoE as the mode
 set device PPPoE:xl0:iinet.net.au
 set authname XXXXXX
 set authkey XXXXXX
 set dial
 set login
 set speed sync
 set ctsrts off
 # Force our end to explicitly monitor for breaks
 # in the connectivity (e.g. the Belkin modem reboots
 # and 'forgets' the bridging of PPPoE frames inbound from
 # iiNet's side.) Default lqrperiod is 30 seconds. Set
 # to reconnect 10seconds after detecting loss (after 5
 # LQR / ECHO requests go unanswered). Must have echo
 # enabled too for this to work, and reconnect set.
 enable echo
 enable lqr
 set lqrperiod 10
 set reconnect 10 0
 # the following 'set ifaddr' only acts to explicitly
 # tell the ppp server side to assign us whatevever IP
 # address it desires on both ends of the PPPoE link
 # (because the "/0" says the server can change any addr bits)
 set ifaddr 10.2.0.1/0 10.2.0.2/0 255.255.255.0 0.0.0.0
 # Override the system's default route to ensure this
 # pppoe link is used as the default path to the Internet
 add default HISADDR
 #
 set timeout 0
 set redial 30 0
#############



Ensuring PPPoE starts at boot time

The following lines are added to /etc/rc.conf to ensure ppp is started at boot time, and brings up the iiNet PPPoE connection on network interface tun0 . The use of "ddial" ensures ppp will continue to try and re-establish the connection whenever the PPPoE link dies for whatever reason.

ppp_enable="YES"         # Start user-ppp
ppp_mode="ddial"         # For details see man page for ppp(8)
ppp_nat="NO"           # We're not using PPP's internal network address translation
ppp_profile="-unit0 iinet"   # Select profile iinet and use /dev/tun0



Updating my public DNS entry whenever the PPPoE link is (re)established

Finally, the following should be placed in /etc/ppp/ppp.linkup to ensure that any changes in my public IP address are captured whenever the PPPoE link comes up. This can occur both at system startup and from time to time during normal operation (either due to iiNet explicitly killing the link, the modem being power cycled or a physical layer glitch).

# When iinet comes up, call my script that updates my dynamic
# DNS entry with zoneedit. Note that this will only occur
# when the ppp system declares the link to have come back up
# (on the assumption that our public IP address doesn't change
# without there being a ppp link transition.)
#
iinet:
 !bg /bin/csh <path_to_script_to_update_dynamic_zonedit_entry>/changeip.sh



Configuring NAT and routing on the FreeBSD 6.0 server

Activated ipnat to perform NAT for other hosts on the local LAN (rather than utilise the NAT function inside ppp itself). The following lines must exist in /etc/rc.conf to ensure we're now a gateway (router) offering NAT functionality.

gateway_enable="YES"
ipnat_enable="YES"


The following lines must exist in /etc/ipnat.rules to establish the correct NAT mapping rules. In this case, all TCP and UDP traffic from 10.1.1/24 (the local LAN) heading outbound via tun0 (the PPPoE interface) will be port re-mapped. Non-TCP or -UDP traffic will be address re-mapped. The "0.0.0.0/32" means "to whatever is the public IP address of tun0".

map tun0 10.1.1.0/24 -> 0.0.0.0/32 portmap tcp/udp 40000:65000
map tun0 10.1.1.0/24 -> 0.0.0.0/32



Tweaking vtund on the FreeBSD 6.0 server

I use vtun in server mode at home on port 5123, protected (as noted below) so that connections can only come in from 136.186.229/24. vtun creates a local network interface tun1.

The following line is added to /etc/rc.conf to ensure vtun is started at boot time:

vtund_enable="YES"

The following in /usr/local/etc/vtund.conf ensures vtun sets up and tears down the appropriate routing table entries when vtun client connections arrive and disconnect.

options {
  port 5123;            # Listen on this port.
  syslog        daemon;
  ppp           /usr/sbin/pppd;           
  ifconfig      /sbin/ifconfig;
  route         /sbin/route;
  firewall      /sbin/ipchains;
  ip            /sbin/ip;
}
default {
  compress no;          # Compression is off by default
  speed 0;              # By default maximum speed, NO shaping
  type  tun;            # IP tunnel
}
caia {
  passwd XXXXX;
  encrypt yes;
  keepalive  yes;
  device tun1;   # Force our vtun on /dev/tun1
   up {
      # 10.3.0.1: tunnel interface (local)
      # 10.3.0.2: tunnel interface (remote)
      ifconfig
        "%% 10.3.0.1 10.3.0.2 mtu 1500";
        # Ensure a public Internet route back to vtun client
        # at the other end
        route "add %a -interface tun0";
        # Now add route to
136.186.229/24 over tunnel
        route "add 136.186/16 10.3.0.2 -hopcount 1";
   };
   down {
        route "delete %a";
        route "delete 136.186/16";
      ifconfig "%% down";
   };
}



Configuring IPF (firewall) on the FreeBSD 6.0 server


The following line must exist in /etc/rc.conf to ensure we're offering IPF firewall functionality.

ipfilter_enable="YES"

The following lines were placed in /etc/ipf.rules to protect the tun0 and tun1 interfaces, whilst allowing inbound ssh (from anywhere) and vtun connections (from work).  Explicitly ensure outbound tcp connections had 'pass out .... keep state' so that returning TCP packets were allowed back in. Protect us from any wierdness like packets arriving from outside (tun0 or tun1 ) but having source addresses taken from my home LANs (10.1.1/24 or 10.1.2/24) or destined to my home LAN broadcast addresses.

# Restrict who can connect to local vtun server on port 5123
pass in quick on tun0 proto tcp from 136.186.229.0/24 to any port = 5123 keep state
# SSH connections allowed from anywhere
pass in quick on tun0 proto tcp from any to any port = ssh keep state
# Otherwise, block all TCP connections from 'the internet'
block in quick on tun0 proto tcp from any to any
# But ensure TCP connections initiated inside the LAN can receive reply
# packets from 'the internet'
pass out quick on tun0 proto tcp from any to any keep state
# Now block 'wierd' packets coming in from wrong source addresses or my
# local broadcast addresses as destinations
block in quick on tun0 from 10.1.1.0/24 to any
block in quick on tun1 from 10.1.1.0/24 to any
block in quick on tun0 from any to 10.1.1.0/32
block in quick on tun0 from any to 10.1.1.255/32
block in quick on tun1 from any to 10.1.1.0/32
block in quick on tun1 from any to 10.1.1.255/32
block in quick on tun0 from 10.1.2.0/24 to any
block in quick on tun1 from 10.1.2.0/24 to any
block in quick on tun0 from any to 10.1.2.0/32
block in quick on tun0 from any to 10.1.2.255/32
block in quick on tun1 from any to 10.1.2.0/32
block in quick on tun1 from any to 10.1.2.255/32
# Otherwise, accept the packet
pass in all


Making the Belkin F1PI241ENau play nice

A number of tweaks are required on the Belkin F1PI241ENau so that it 'plays nice' when relegated to simply being a bridge for PPPoE traffic.

Switch from PPPoE to RFC1483 Bridging

The default way to use this Belkin router is for multiple LAN hosts to hang off the built-in 4-port Ethernet switch, with the Belkin providing NAT between the LAN side and the WAN side. The Belkin's WAN interface is normally configured to establish an authenticated PPPoE connection to iiNet over the single active ATM VC (virtual channel, typically VPI/VCI of 8/35).

The new configuration involves setting the WAN interface to use "1483 Bridging" rather than "PPPoE" on the single active VC configured to talk to iiNet. This can be found under Advanced Settings -> WAN -> ATM PVC. Click on "VC1" (assuming VC1 is the active PVC currently used for PPPoE). Set the protocol to "
1483 Bridging" and the encapsulation to "LLC". I left other parameters as-is: VLAN "default", QoS Class "UBR", PCR/SCR/MBS  "4000/4000/10" and MSS "1452". (The setting for VLAN assumes that all four LAN ports are currently associated with the "Default" VLAN. Alternate configurations are not discussed here.)  Use "Save Settings" to make the change.

Restarting the Belkin's VoIP ATA

Before August 2007 I had the Belkin's VoIP ATA configured to register and authenticate with an Asterisk server on 10.1.1.3 (which would itself register with iiNet's VoIP service). When the Belkin's ATM interface is first switched to "1483 Bridging" mode, the VoIP ATA appears to be disabled (and the VoIP LED stays off). Adding the following route into the Belkin's "Route->Routing Table" menu brings the VoIP ATA back up again:

        Destination 0.0.0.0   Mask  0.0.0.0  Gateway 10.1.1.3

The "VoIP" LED should almost immediate light up again as the ATA re-registers itself with the Asterisk server on 10.1.1.3. (My home VoIP service is documented elsewhere.)

Interesting note - multiple PPPoE sessions

While initially experimenting with running PPPoE through the Belkin router in January 2007 (with firmware 0.35 at the time) I noticed the ability to support concurrent PPPoE sessions. The Belkin allows PPPoE sessions on the LAN side to be bridged through to the ISP (e.g. iiNet) even when the Belkin itself is running PPPoE on its ATM WAN interface. If the ISP allows multiple concurrent PPPoE sessions (which iiNet did at the time), you will have two quite valid public IP addresses - one assigned to the Belkin's PPPoE session, and one assigned to the PPPoE session originated by another host on your LAN. Both PPPoE sessions were sharing the same, single ATM PVC (8/35) to iiNet's DSLAM. I did not rely on this behaviour as iiNet did not officially guarantee support for concurrent PPPoE sessions. (Note for anyone from whirlpool reading this far: Getting mutiple public IP addresses at the same time does not increase the amount of aggregate bandwidth you receive. The result is that you can route traffic in or out of your home LAN via two distinct IP addresses, but the total number of bits/second or packets/second is no different to when you had a single IP address.)