# Building a home router as an exercise in learning



## jdakhayman (May 4, 2015)

As a learning exercise I have began a project to build a home router using FreeBSD 10.1. I took the notion when I read this blog post by Kris Moore of the PC-BSD project http://blog.pcbsd.org/2015/01/using-trueos-as-a-ipfw-based-home-router/ I know that there are several good and capable NAT/firewall packages available such as pfsense and opnsense. I have used pfsense before, and it does it job well, but as mentioned above, the desire to learn how to do it, and hopefully, in the process learn more about networking and FreeBSD in general is my purpose.

Now of course, I wouldn’t be writing this if I were not having problems. Due to some differences in my service provider I was unable to follow the above blog post exactly. I will try to outline what my situation is, then try to explain what I have already done. Then explain what's not working.

The equipment. I have a http://www.pcengines.ch/apu1d4.htm . The apu1d4 uses Realtek RTL8111E network interfaces, which FreeBSD 10.1 now has good support for now. It used to be a bit sketchy, but much better now. I am also using a Compex mini-PCIe wi-fi adapter Model WLE200NX a/b/g/n for the wireless card inside of it. The card uses an Atheros chipset. It also uses an Intel 30 gb msata ssd as the hard drive. I used a standard FreeBSD 10.1 USB image, enabled the serial console in /boot/loader.conf and installed without any issues.

Now that I have a running system with stock FreeBSD 10.1 and a fresh `freebsd-update fetch update` Ill give some background on some of my particulars. My network provider has fiber to my home, but it still uses pppoe to make the connection. The provider has a demarc device that does nothing more than bridge the connection over to me. So that's the big wrinkle in the fabric. 

My intentions were then to assign one of the interfaces as my WAN uplink using pppoe and then to bridge the remaining wired interfaces with the wireless interface. Thus, creating a router basically like one that can be bought in a store for much cheaper and alot less aggravation, but I degress.

To keep the initial post from being one large wall of text I'll start a second post to explain my configuration.


----------



## jdakhayman (May 4, 2015)

I'll start the explanation of my configuration with posting the relevant  config file. First I'll post the /etc/rc.conf:


```
# File System and CPU
zfs_enable="YES"
powerd_enable="YES"
powerd_flags="-a hiadaptive -b adaptive"

# Networking Section

# This sets the LAN default gateway.
defaultrouter="192.168.2.1"

# Set Host name for the router
hostname="fletcher-0.lan"

# Uplink to ISP. Using PPP to create the connection. It will create a
# tun interface. This is setup in /etc/ppp/ppp.conf
ppp_enable="YES"
ppp_nat="NO"
ppp_mode="ddial"
ppp_profile="yadtel"

# Make this machine act as a gateway (router).
gateway_enable="YES"

# Bridge setup and WPA wireless access point.
cloned_interfaces="bridge0"
ifconfig_bridge0="addm re0 addm re2 addm wlan0 up"
ifconfig_bridge0_alias0="inet 192.168.2.1 netmask 255.255.255.0"

# Brings up and configures the wirless interface to add to the bridge
wlans_ath0="wlan0"
create_args_wlan0="wlanmode hostap"
ifconfig_wlan0="up ssid devop328 mode 11g"

# Bring up wired interfaces to add to the bridge.
ifconfig_re0="up"
ifconfig_re2="up"

# Start hostapd. This is used to authorize WPA wireless clients.
hostapd_enable="YES"

# Firewall setup (using ipfw)
firewall_enable="YES"
firewall_logging="YES"
firewall_script="/etc/ipfw.rules"

# NATD
natd_enable="YES"
natd_interface="bridge0"
natd_flags="-m -f /etc/natd.conf"


# Secondary router services
sshd_enable="YES"
dhcpd_enable="YES"
dhcpd_ifaces="bridge0"
# ntpd_enable="YES"
# ntpd_sync_on_start="YES"
```

As can be seen in the posted code above. I have set the default gateway, set PPP to start up, and demand a connection at all times, enable routing, made my bridge and added the interfaces and configured the wireless card to act as an AP. Hostapd is also started to authenticate wireless hosts.

IPFW is then started using a custom rule script and is using userland NATd as well (Once I figure out everything I plan to move to IPFW in-kernel NAT).  Lastly sshd and dhcp are started. NTP complains to much if the uplink connection fails so I have it commented out  until I can fix it.

Next is my /etc/ppp/ppp.conf

```
#################################################################
# PPP  Sample Configuration File
# Originally written by Toshiharu OHNO
# Simplified 5/14/1999 by wself@cdrom.com
#
# See /usr/share/examples/ppp/ for some examples
#
# $FreeBSD: releng/10.1/etc/ppp/ppp.conf 203943 2010-02-16 01:07:06Z jkim $
#################################################################
# Original config file is located as ppp.conf.old_05_03_15.
# Using a configuration from forum post
# https://forums.freebsd.org/threads/pppoe-connection.23500/

default:
  set log Chat Command Connect Filter Phase tun Error Alert
yadtel:
  set device PPPoE:re1
  set redial 1 0
  set reconnect 3 23
  set mtu max 1492
  set mru max 1492
  set speed sync
  set server /var/run/internet "" 0177
  set dial
  set login
  set authname myusername
  set authkey mypassword
  disable acfcomp protocomp
  disable ipv6cp
  enable mssfixup
  enable dns
  enable lqr
  enable echo
  accept lqr
  add! default HISADDR
  set timeout 0
  open
```

This configuration works as best as I can tell. It does write to /etc/resolv.conf the nameservers that are provided by the service provider. I can also ping addresses and even browse sites using lynx. Of course all over the serial connection at this point. But once I have the defaultrouter and ipfw and NATd enable in the rc.conf I can no longer `ping` or `traceroute` or browse with lynx directly from the router

Here are my ipfw ruleset. I copied these over from the blog post and changed what need to be changed for my setup. /etc/ipfw.rules:

```
#!/bin/sh
# Flush out the list before we begin.
ipfw -q -f flush

# Set rules command prefix
cmd="ipfw -q add"
pif="tun0" # interface name of NIC attached to Internet
iif="bridge0" # interface name of NIC attached to LAN
server="192.168.2.1"
inside="192.168.2.0/24"
ks="keep-state" # Laziness
skip="skipto 600"

# Allow everything through the local NIC
######################################
$cmd 00020 allow all from any to any via bridge0

######################################
# No restrictions on Loopback Interface
######################################
$cmd 00025 allow all from any to any via lo0

# NAT the inbound stuff
######################################
$cmd 00100 divert natd ip from any to any in via $pif # NAT any inbound packets

######################################
# Allow packet through if it matches existing entry in dynamic rules

######################################
$cmd 00105 check-state

######################################
# Allow all outgoing packets
######################################
$cmd 00110 $skip all from any to any out via $pif $ks

# Deny all inbound traffic from non-routable reserved address spaces
######################################
$cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP
$cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP
$cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP
$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback
$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback
$cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config
$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for doc's
$cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect
$cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast
######################################

# Deny public pings
######################################
$cmd 00310 deny icmp from any to any in via $pif

# Log all the other troublemakers
$cmd 00550 deny log all from any to any

# Skip location for NATD
$cmd 600 divert natd ip from any to any out via $pif # skipto location for outbound stateful rules
$cmd 610 allow ip from any to any
```

I am openly admitting that I have very little understanding with firewall rule sets and working on learning more. That is why I did just copy over verbatim from the blog post. So I have a bad feeling this is where I'm having the problems.

Now here is the /etc/natd.conf

```
interface bridge0
use_sockets yes
same_ports yes
dynamic yes
log_denied yes
log yes

# Optionally if you run services behind NAT and need to forward ports, you can do so with syntax like the following:
# Sample redirect port
# redirect_port tcp 192.168.1.100:80 80
# redirect_port tcp 192.168.2.100:995 995
```

Once again I copied it over from the blog post, but made changes relevant to my setup.
Now that my configuration has mostly been displayed I'll finish off with my problem in the next post.

--jda


----------



## jdakhayman (May 4, 2015)

As it stands right now this is what works as best as I can tell.

I can can connect a system to the router either to a wired port or thought wireless, and receive an ip address from the DHCP server. I can ssh in the router using the address assigned as my default router 192.168.2.1. I can have two systems attached to the router and ssh in to the other system without issue. This leads me to assume that I have the bridge setup correctly. The problems start when I connect with a desktop system or a smart phone or a laptop, and open a browser and open a web page it cant reach it. It just times out.

I have run `netstat -rm` and here is the out put of that: ( I left out the ipv6 stuff)

```
Internet:
Destination       Gateway       Flags  Netif Expire
default              66.44.248.1  UGS  tun0
66.44.243.70    link#8           UHS  lo0
66.44.248.1      link#8           UHS  tun0
127.0.0.1          link#5           UH    lo0
192.168.2.0/24 link#6           U      bridge0
192.168.2.1      link#6           UHS  lo0
```

I've made the assumption it has to do with NAT and/or the firewall. If I comment out the default route and all the ipfw and NAT stuff in the /etc/rc.conf I can ping and browse only from the router machine, but still nothing on the bridge interface. With ppp creating my uplink connection do I still need the defaultrouter setting in the rc.conf?

I've look at many different guides and so far I do see to many different ways of doing it other that what I have listed here. I would love some critique, and if I'm doing something silly in my setup please let me know. If further information is needed I'll do my best to get it posted. Thanks for looking.

jda


----------

