~ / sysadmin / netbsd / ADSL router
sysadminA home ADSL router running NetBSD
A small fanless appliance, a PCI ADSL card and a full Unix on the edge of the network. The result does its own dialling, filtering and forwarding, and it is far more fun than a sealed box from an internet provider.
The hardware
The base is a Soekris single board computer running NetBSD. A Traverse Viking ADSL2+ PCI card provides the line side. Together they were tested against two national providers and held up on both.
Dialling with PPPoE
The line is a PPPoE session, and NetBSD has both a manual page and a user guide for it. When the session refuses to come up, the debug flag on the interface is the quickest way to see the negotiation.
ifconfig pppoe0 debug
Do not forget MSS clamping
Many sites will simply never load without correct maximum segment size handling, because the router ends up advertising a segment size larger than the path can carry. Clamping the value fixes it, and it has to be set in two places: once for traffic the router itself originates, and once for traffic passing through with network address translation.
# for the router itself
net.inet.tcp.mss_ifmtu=1
# for machines behind the router, in the packet filter rules
scrub in all fragment reassemble max-mss 1452
Set the firewall value to match the real path. A value that is too large brings the old symptoms straight back.
The stubborn card
The ADSL card had one annoying habit: once its configuration had been saved, the management interface would not appear after a reboot. Reaching the card meant resetting it and entering the configuration again, which is tolerable once and unbearable weekly.
The workaround is to treat the card's configuration as ephemeral. Apply it on boot from the router and leave the card's own saved configuration empty, so its management interface stays reachable. A small Perl script drives the card's own command interface over the network and replays the settings each time the router starts.
#!/usr/pkg/bin/perl
use Net::Telnet ();
my @steps = (
'ip delete interface ipwan',
'bridge add interface br0',
'bridge attach br0 ethernet',
'rfc1483 add transport tr1 a1 8 35 llc bridged',
'bridge add interface br1',
'bridge attach br1 tr1',
# deliberately not saved
);
my $t = new Net::Telnet (Timeout => 10, Prompt => "/--> $/");
$t->open("192.168.1.1");
$t->login("admin", "admin");
for my $step (@steps) {
my @out = $t->cmd($step);
print "step: $step => @out\\n";
}
Where to read more
Background on PPPoE and the board is listed on the resources page.