PPPoE Router and Firewall

From OpenBSD-Wiki

Jump to: navigation, search
Written for: OpenBSD Version 3.9
Written for: OpenBSD Version 4.0

Contents

[edit] Summary

This article is going to explain how to get OpenBSD to be your network's gateway / firewall / NAT router using a PPPOE connection to the upstream ISP. It should be used as a template and guide and should certainly not be read without a basic knowledge of TCP/IP, nor should it supersede reading the OpenBSD PF user's guide and the appropriate manual pages.

To get started checkout the following manual pages. You don't need to understand everything in these pages but you should read over them in order to know where to go for help later.

This article is mostly complete but is lacking in some areas. Expect changes as we work on getting it up to the high standards of true openbsd documentation.

[edit] Conventions

In order to make this article clearer to read we'll use fxp0 and rl0 as the names for the internal and external interfaces. Of course you'll want to change these values to suit your individual site.

  • fxp0: Internal network interface, used for the local area network.
  • rl0: The pppoe side of the network connection. This is the live publicly routable IP address of your firewall.

[edit] Kernel mods

First thing we need to do is enable packet forwarding between interfaces, so we need to modify /etc/sysctl.conf by uncommenting the net.inet.ip.forwarding=1 line such that it looks like this:

Config File: /etc/sysctl.conf
net.inet.ip.forwarding=1

We need to modify that file so that upon system start up it will automatically change it to that setting. To change the current setting without rebooting, run the following command:

Command: sysctl net forwarding
# sysctl net.inet.ip.forwarding=1

[edit] Configure external interface

[edit] PPPoE Internet

pppoe (4) is the kernel mode drive and came out in OpenBSD 3.7. You need to create a file named /etc/hostname.pppoe0 and fill it out with the appropriate settings. There was a change in the syntax and method for using pppoe(4) between OpenBSD 3.9 and 4.0. Look at the appropriate section for whatever version you are running. You can specify the IP (substitute 0.0.0.0 with the IP if you have a static connection). Change the USERNAME (it may be your email address on the primary account) and PASSWORD with your username and password, respectively.

Note: Is it possible to mix a fixed IP with a wildcard gateway? That is, if you specify something valid for "0.0.0.0" can you continue to accept whatever your provider returns as a gateway via 0.0.0.1 as an argument for the dest_address and default route?

[edit] OpenBSD 3.9

In OpenBSD 3.9 the pppoe tunnel is managed via a userland utility called spppcontrol.

Config File: /etc/hostname.pppoe0
pppoedev rl0
!/sbin/ifconfig rl0 up
!/usr/sbin/spppcontrol \$if myauthproto=pap myauthname=USERNAME myauthkey=PASSWORD
!/sbin/ifconfig \$if inet 0.0.0.0 0.0.0.1 netmask 0xffffffff
!/sbin/route add default 0.0.0.1
up

[edit] OpenBSD 4.0

As of OpenBSD 4.0 configuration of the pppoe(4) device is via the regular ifconfig interface.

Config File: /etc/hostname.pppoe0
inet 0.0.0.0 255.255.255.255 NONE pppoedev rl0 \
	authproto pap authname 'USER' authkey 'PASSWORD' up
dest 0.0.0.1
!/sbin/route add default 0.0.0.1

The physical connection to your DSL modem will use the external interface for establishing the tunnel. The actual internet traffic will flow through the PPPOE tunnel. This matters when talking to software such as pf otherwise the software looks at the wrong interface for packets.

You may also want to restrict access to this file as it has your PPPoE password. To do this run:

Command: restricting access to /etc/hostname.pppoe0
# chmod go-rwx /etc/hostname.pppoe0

[edit] Configure the physical network interface

The PPPOE tunnel will be established via a regular ethernet connection to your DSL modem. There is no IP configuration for the physical interfaces so all we have to do is make sure netstart(8) marks the interface as up at boot.

Command: Set /etc/hostname.rl0
echo up > /etc/hostname.rl0

The presence of /etc/mygate will interfere with the routing table. Make sure this file is either empty or does not exist.

Command: remove /etc/mygate
rm -f /etc/mygate

[edit] Restart all network interfaces to bring pppoe up

You can run sh /etc/netstart to have your network reload it's settings. Make certain your pf firewall is disabled or else the PPPoE packets won't pass through.

Command: Restart all network interfaces
# sh /etc/netstart

[edit] Configure internal interface

We now need to place a file so that our system knows the bring it up with an IP address. Personally, I like my servers to use high numbers and users to use low numbers. The highest (254) is always my gateway. I choose the 10.0.0.0/8 because few people use it -- which means less chance of a collision (If you have 192.168.0.16 locally and VPN in to a location that has that IP address assigned elsewhere then you may end up having problems).

Config File: /etc/hostname.fxp0
inet 10.10.2.254 255.255.255.0 NONE

[edit] DHCP Server

We want a DHCP server on our LAN so computers can get IP's automagically, so let's get that configured. Their are two main files: /etc/dhcpd.conf (5) and /etc/dhcpd.interfaces. Both are fairly simple to figure out. Also, change the domain-name-servers to fit your dns servers that your ISP gave you.


Config File: /etc/dhcpd.conf
# See dhcpd.conf(5) and dhcpd(8) for more information.

shared-network LOCAL-NET {
        option  domain-name "mydomain.com";
        option  domain-name-servers 151.164.1.8, 206.13.28.12;

        subnet 10.10.2.0 netmask 255.255.255.0 {
                option routers 10.10.2.254;
                range 10.10.2.30 10.10.2.50;
        }
}

If you want to have a certain MAC address always get the same IP (if you have forwarding rules, for example) then you would add a host mapping. Below is an example. Obviously, replace somenamehere with whatever label you would like to attach to it. The clients don't care about the label so make it useful for yourself. This part is useful for port forwarding, but you need to maintain DHCP for simplicities sake (for example, you have a laptop you take to work and bring back home; so keeping DHCP makes your life a bit easier with less settings to change).

Config File: /etc/dhcpd.conf
host somenamehere {
        hardware ethernet 00:0C:8D:16:E0:AD;
        fixed-address 10.10.2.49;
}

Now for the /etc/dhcpd.interface all you need is a single line that says the interface name that it should answer on so you file would like look this if your interface was 'bce0':

Config File: /etc/dhcpd.interfaces
fxp0

The preferred method of starting dhcpd is by using /etc/rc.conf.local and appending the following:

Config File: /etc/rc.conf.local
dhcpd_flags=""

Before you want to rely on that you should make certain your config file is sane. You should also check this every time you change it by doing the following:

Commands: Using -n with dhcpd
# /usr/sbin/dhcpd -n -c /etc/dhcpd.conf

And to load it by hand, so you don't have to reboot run the same command as you did in /etc/rc.local:

Command: Launching dhcpd
# /usr/sbin/dhcpd fxp0

[edit] DNS

Having a local DNS server is beneficial for two reason:

  • Local caching
  • Able to use redirects here instead of at PF for locally hosted servers

Named (version 9) comes with OpenBSD 4.0 by default and is also configured as a local caching network, all you have to do is enable it. To do so, make the following chance to /etc/rc.conf.local

Config File: /etc/rc.conf.local
named_flags=""

To start up named without having to reboot, simply type named as root.

[edit] Firewall and NAT

We will use PF (4) as our firewall and NAT because it is included in the default OpenBSD install and has proven itself over time. There is a great book on PF(4) that should be read before you start hacking your own pf.conf. Each site will have a different pf.conf tailored for their own situation. The example below should give you a good starting point but it is no substitute for reading the full users guide.

It is important to know to check for the most recent changes on the version you are installing (if your rules are made from another version) to make sure you don't need to make any changes. For example, the 4.0 to 4.1 release made a significant amount of changes.

The below pf.conf comes directly from the users guide. It has very specific goals:

  • Allow only SSH, Auth/Ident, and ICMP Echo requests to come in
  • Default deny for everything else
  • Unrestricted internet access for internal computers
  • Redirect Port 80 towards a internal webserver called comp3
  • Log filter stats
  • By default, reply with a TCP RST or ICMP unreachable.
  • Keep it simple.
Note: You need to enable PF *after* your have established a PPPoE connection otherwise PF will block it; if anyone knows if the rules to allow this, please post on the discussion page
Note: If you use DSL: You may want to add "scrub out on $extIF max-mss 1440" to your pf.conf, otherwise sites like digg.com, myspace.com, and some online games may not work correctly
Note: When you use pppoe0, you need to reference that in your pf.conf instead of your physical external device.

Again it is very important that you understand as much as you can about pf before you start to use it.

Config File: /etc/pf.conf
# macros
ext_if="pppoe0"
int_if="fxp0"

tcp_services="{ 22, 113 }"
icmp_types="echoreq"

comp3="192.168.0.3"

# options
set block-policy return
set loginterface $ext_if

set skip on lo

# scrub
scrub in

# nat/rdr
nat on $ext_if from !($ext_if) -> ($ext_if:0)
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"

rdr pass on $int_if proto tcp to port ftp -> 127.0.0.1 port 8021
rdr on $ext_if proto tcp from any to any port 80 -> $comp3

# filter rules
block in

pass out keep state

anchor "ftp-proxy/*"
antispoof quick for { lo $int_if }

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

pass in on $ext_if inet proto tcp from any to $comp3 port 80 \
    flags S/SA synproxy state

pass in inet proto icmp all icmp-type $icmp_types keep state

pass quick on $int_if

If you want to leave a backup or share your pf.conf, feel free to do so at PF Examples

Personal tools