Setting up dialup gateway with OpenBSD

This document is a guide to setting up OpenBSD to act as a gateway between a small private ethernet network and the Internet using a dial-up connection to an ISP. It assumes that an initial install of OpenBSD has been done and has basic examples of configuring various services.

As the gateway is going to be connected to the Internet, care should be taken with security. Many of the configuration files and programs will need root permission to use. Always be careful to set access to files to the minimum required. Set up sudo, and use it.

Index


Setting up local networking

[top]

IP addressing

Our internal network should use a network address from one of the ranges that have been set aside for private networks in RFC1918.

The addresses suitable are:

For this document we're using 192.168.33.0/24 as our local network.

It's traditional to put routers, gateways, etc in a block at the top or bottom of the network address range. For this server we're using 192.168.33.1. To achieve this /etc/hostname.if has a single entry:

inet 192.168.33.1 255.255.255.0 NONE

DHCP

Clients on the internal network need an appropriate IP address. We provide this, along with other information on the network configuration. DHCP provides a way of centrally configuring the information and getting it to the clients on the network. The DHCP daemon must be enabled by editing /etc/rc.conf as described in the comments in rc.conf.

The DHCP daemon has it's configuration in /etc/dhcpd.conf. For a basic configuration something like this will do:

subnet 192.168.33.0 netmask 255.255.255.0 {
        default-lease-time 86400;
        max-lease-time 604800;
        option domain-name "home.net";
        option domain-name-servers 192.168.33.1;
        option routers 192.168.33.1;
        range 192.168.33.65 192.168.33.126;
}

The lease time is set to a minimum of one day (86400 seconds) and a maximum of one week (604800 seconds). On a small network with little activity in the way of hosts coming and going there is no need to have short lease lengths.

The domain name options point to the nameserver that will be set up next.

The router option is only needed if access to the Internet is going to be enabled with NAT. It doesn't hurt to have it even if it is not being used.

The range is is set to 192.168.33.64/26 to allow it to be easily specified in case we want to apply firewall rules just to the DHCP clients.

DNS

We will need basic DNS services for the local network. DNS configuration files are in /var/named. We will need to add some lines to /var/named/etc/named.conf, and create two zone files in /var/named/master.

Add to the section of /var/named/etc/named.conf that describes the options:

        forward only;
        forwarders { 202.37.66.18; 202.37.66.19; 202.14.102.2; };

Substitute the nameserver(s) that your ISP supplies for these examples in your named.conf. If there is more than one nameserver, a semicolon seperated list is required.

Towards the end of named.conf is the section describing the master zones. Add two master zones, one for name to number and one for number to name.

zone "home.net" {
        type master;
        file "master/home";
};
zone "33.168.192.in-addr.arpa" {
        type master;
        file "master/home.rev";
};

In /var/named/master create two files, home.rev and home. These will be the zone files for the internal network.

In /var/named/namedb/home.rev:

$ORIGIN 33.168.192.in-addr.arpa.
$TTL 6h

@       IN      SOA     gateway.home.net. admin.gateway.home.net.  (
                                1       ; Serial
                                3600    ; Refresh
                                900     ; Retry
                                3600000 ; Expire
                                3600 )  ; Minimum
        IN      NS      gateway.home.net.
1       IN      PTR     gateway.home.net.
65      IN      PTR     dhcp65.home.net.
66      IN      PTR     dhcp66.home.net.
67      IN      PTR     dhcp67.home.net.

In /var/named/namedb/home:

$ORIGIN home.net.
$TTL 6h


@ IN SOA gateway.home.net. admin.gateway.home.net. (
                1          ; serial
                3600       ; refresh
                900        ; retry
                3600000    ; expire
                3600 )     ; minimum

        IN      NS      gateway

localhost IN	 A       127.0.0.1
gateway  IN      A       192.168.33.1
proxy    IN      CNAME   gateway
dhcp65   IN      A       192.168.33.65
dhcp66   IN      A       192.168.33.66
dhcp67   IN      A       192.168.33.67

Make sure named is enabled in /etc/rc.conf.

The DNS client configuration file, /etc/resolv.conf, should look like this:

search home.net
nameserver 127.0.0.1

What you should end up with is a nameserver that will service all local hosts with local information. If it gets a query about a remote host it will forward the request to the ISPs nameserver(s). When the ppp link is down, the request will time out and the query will fail with "host or domain doesn't exist". When the link is up the request will should succeed in the normal manner.

When a host is added to the network, it's good practise to make appropriate entries in both zone files. If you want a host to have several names, add a CNAME entry to the 'home' zone file. Each time a change is made to a zone file, change the serial number and use

rndc reload

to get the name server to load up the changes.

PPP

[top]

To get ppp going you will need to know the port name to use, and some basic information from the ISP.

Basic Info from ISP
Account namephilip
Passwordpassword
Dial086755555
Nameserver202.12.123.43

System Info
Modem/dev/cua00
Speed19200

Use 19200 as the connect speed to get things working. After succesful connections have been made, this speed can be raised to whatever your modem supports. Remember that PC compatable systems only support limited speeds, refer to the pccom man page for details.

/etc/ppp/options

Needs the device name of the modem, the speed to connect at, and the name of the account with the ISP.

/dev/cua00
19200
defaultroute
lock
noipdefault
persist
name philip
connect "/usr/sbin/chat -v -f /etc/ppp/isp.chat"

The defaultroute setting actually sends the traffic out the modem once the connection is up. Lock sets a lock on the serial port so other programs know it's in use. Noipdefault allows the ppp daemon to negotiate the IP address with the ISP. The ISP will normally assign an IP when the connection is made. Persist keeps the connection up. If the connection goes down for any reason, the PPP daemon will redial and attempt to get it back going. Useful if you get a lot of droputs.

The 'name' option is needed by the ISP. By default ppp uses the hostname of your computer. The 'name' option sends the account name.

The chat script is called by the last line.

/etc/ppp/isp.chat

Needs the phone number of the ISP.

ABORT "NO CARRIER"
ABORT "NO DIALTONE"
ABORT "ERROR"
ABORT "NO ANSWER"
ABORT "BUSY"
"" "at"
OK "at&d0&c1"
OK atdt086755555
CONNECT  ""

The chat script dials the number of the ISP, then waits for CONNECT. If you don't wait for the CONNECT, the ppp daemon will exit because it doesn't have carrier.

/etc/ppp/pap-secrets

Needs the account name and password for the ISP.

# Secrets for authentication using PAP
# client        server  secret                  IP addresses
philip  *       password  *

The pap-secrets file is where the account and password details are kept. It uses 'philip' and 'password' for any server and any IP address.

To make the connection to the ISP, use the command:

pppd 

Recent versions of OpenBSD don't create the ppp device by default. If you get an error saying ppp0 doesn't exist, create the device with

ifconfig ppp0 create

This will be needed after each restart of the system, so consider putting this command in /etc/rc.local or in a script to start ppp.

To drop the connection use the command:

kill `cat /var/run/ppp0.pid `

To check the status of your PPP connection, some useful things to do are:

/sbin/ifconfig ppp0

You can check the log files for messages from PPP.

tail -f /var/log/daemon

NAT/Firewall

[top]

NAT

Network address translation is handled by the OpenBSD packet filter, 'pf'.

The packet filter is configured by editing the config file, /etc/pf.conf. To translate our internal network addresses to the address negotiated for our PPP connection we configure some macros in /etc/pf.conf. There are some commented out macros that define the internal and external interfaces and networks.

# Macros: define common values, so they can be referenced and changed easily.
ext_if="ppp0"   # replace with actual external interface name i.e., dc0
int_if="le0"    # replace with actual internal interface name i.e., dc1
internal_net="192.168.33.0/24"
#external_addr="192.168.1.1"

You can see here we have set the ppp interface as the external interface, and the ethernet interface as the internal. We know the internal network addresses, so we set those too. We don't know what the external network numbers will be, so these are left undefined.

Further down the config file we find the section that does the NAT. All we need to do is uncomment the line that specifies what to NAT.

# Translation: specify how addresses are to be mapped or redirected.
# nat: packets going out through $ext_if with source address $internal_net will
# get translated as coming from the address of $ext_if, a state is created for
# such packets, and incoming packets will be redirected to the internal address.
nat on $ext_if from $internal_net to any -> ($ext_if)

That's it. When the ppp connection is up pf will nat the internal network addresses to whatever is allocated on the external interface by the ISP.

Firewall

For simple firewalling, we can block incoming connections while allowing outgoing connections. There is already an example that does nearly what we want. Just edit the section like this:

# block all incoming packets but allow ssh, pass all outgoing tcp and udp
# connections and keep state, logging blocked packets.
block in log all
pass  in  on $ext_if proto tcp from any to $ext_if port 22 keep state
pass  out on $ext_if proto { tcp, udp } all keep state
pass in on $int_if from $internal_net to any keep state
pass in on lo0 all
pass out on lo0 all

The last three lines allow the internal network to get out, and the local host to talk to itself. If you want to view the logging, you'll need to understand tcpdump. The logs can be viewed in real time with the following commands:

/sbin/ifconfig pflog0 up           
/usr/sbin/tcpdump -n -l -i pflog0    

Another userful command for a realtime look at what the connection is netstat. This shows the number of bytes in and out, refreshed every five seconds:

netstat -b -w 5 -I ppp0

Enabling pf

When a connection is made by ppp, pf must be started and the kernel must be told to forward IP packets. In /etc/ppp create two files, ip-up and ip-down. These are run by the ppp daemon when an IP connection is established and when it stops.

ip-up
#! /bin/sh
/usr/sbin/sysctl -w net.inet.ip.forwarding=1
/sbin/pfctl -e -f /etc/pf.conf

ip-down
#! /bin/sh
/sbin/pfctl -d 
/usr/sbin/sysctl -w net.inet.ip.forwarding=0

The man pages for sysctl, pfctl, and pppd can be referred to for additional information.


Philip Plane <philip@xinqu.net>