Chapter 25. Setting up TCP/IP on NetBSD in practice

Table of Contents

25.1. Overview of the network configuration files
25.2. Connecting to common LAN setups
25.2.1. Connecting using IEEE 802.11 (Wi-Fi)
25.3. Manually creating a small LAN
25.4. Connecting to a home/office ISP with PPPoE
25.4.1. Configuring a VLAN
25.4.2. Setting up MSS clamping
25.4.3. Obtaining IPv6 addresses via Prefix Delegation
25.5. Setting up an Internet gateway with NPF
25.6. Setting up a network bridge device
25.6.1. Bridge example
25.7. Ensuring interfaces are initialized in the correct order
25.8. Some useful commands

25.1. Overview of the network configuration files

The following is a list of the files used to configure the network. The usage of these files, some of which have already been met the first chapters, will be described in the following sections.

/etc/hosts

Local hosts database file. Each line contains information regarding a known host and contains the internet address, the host's name and the aliases. Small networks can be configured using only the hosts file, without a name server. See hosts(5)

/etc/resolv.conf

This file specifies how the routines which provide access to the Internet Domain Name System should operate. Generally it contains the addresses of the DNS servers. See resolv.conf(5)

/etc/sysctl.conf

This file is used for configuring kernel settings, e.g. enabling packet forwarding on a gateway. See sysctl.conf(5).

/etc/ifconfig.xxx

This file is used for the automatic configuration of the network interfaces at boot, see ifconfig.if(5)

/etc/npf.conf

Contains firewall configuration for the NetBSD Packet Filter, see npf.conf(5) and /usr/share/examples/npf.

/etc/dhcpcd.conf

Contains configuration for a DHCP client. DHCP is used to automatically get IPv4 address assignments over Ethernet, but dhcpcd(8) is also used to for IPv6 Prefix Delegation and DHCPv6. See dhcpcd.conf(5) and /usr/share/examples/dhcpcd.

/etc/dhcpd.conf

Contains configuration for a DHCP server. DHCP is used to automatically assign IPv4 addresses to clients. See dhcpd.conf(5) and /usr/share/examples/dhcpd.

/etc/mygate

Contains the IP address of the gateway. Used to configure a default route when not using DHCP.

/etc/nsswitch.conf

Name service switch configuration file. It controls how a process looks up various databases containing information regarding hosts, users, groups, etc. Specifically, this file defines the order to look up the databases. For example, the line:

hosts:    files dns mdnsd

specifies that the hosts database comes from two sources, files (the local /etc/hosts file) and DNS, (the Internet Domain Name System) and that the local files are searched before the DNS.

It is usually not necessary to modify this file except to enable Multicast DNS.

See nsswitch.conf(5).

/etc/hostapd.conf

Used to configure an IEEE 802.11 (Wi-Fi) wireless access point. See hostapd.conf(5) and /usr/share/examples/hostapd.

/etc/wpa_supplicant.conf

Used to configure an IEEE 802.11 (Wi-Fi) client. See wpa_supplicant.conf(5) and /usr/share/examples/wpa_supplicant.

25.2. Connecting to common LAN setups

In Local Area Networks that are centrally managed, one can expect Internet connectivity being available via some router, a DNS server being available, and most important, a DHCP server which hands out IP addresses to clients on request. To make a NetBSD client run in such an environment, it's usually enough to set

dhcpcd=YES

in /etc/rc.conf, and the IP address will be set automatically, /etc/resolv.conf will be created and routing setup to the default router.

25.2.1. Connecting using IEEE 802.11 (Wi-Fi)

WPA Supplicant allows connecting to Wi-Fi networks using a password, but also provides a consistent interface through which to connect to access points.

As well as having dhcpcd(8) running, on a system using Wi-Fi to connect to an access point, wpa_supplicant(8) must typically be enabled:

ifconfig_iwm0="up"
dhcpcd=YES
wpa_supplicant=YES

At runtime:

# ifconfig iwm0 up
# service dhcpcd start
# service wpa_supplicant start

In this case, our Wi-Fi interface is called iwm0. It is set to up with ifconfig(8). You can find a list of detected Wi-Fi interfaces with wlanctl(8):

# wlanctl -a
iwm0: mac 10:02:xx:xx:xx:xx bss 00:00:00:00:00:00

The following /etc/wpa_supplicant.conf configures NetBSD to automatically connect to two access points. More can also be added.

Example 25.1. /etc/wpa_supplicant.conf

# Allow wpa_cli(8) to configure wpa_supplicant
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1

# Automatically connect to the unprotected network "metalab".
network={
	ssid="metalab"
	key_mgmt=NONE
	priority=100
}

# Automatically connect to the protected network "discord" using the password "XXX".
network={
        ssid="discord"
        psk="XXX"
}

After adding access points, reload wpa_supplicant(8)'s configuration:

# service wpa_supplicant reload
# service dhcpcd restart

You can use wpa_cli(8) to scan for networks once WPA supplicant is running:

# wpa_cli scan
# wpa_cli scan_results
Selected interface 'iwm0'
16:01:33.578: bssid / frequency / signal level / flags / ssid
xx:xx:xx:xx:xx:xx       5180    91      [WPA2-PSK-CCMP][ESS]    FRITZ!Box 1000 EZ

25.3. Manually creating a small LAN

This section describes how to configure a LAN manually in order to describe the basics of the networking stack. Usually, this configuration is automatic through dhcpcd(8), see Section 25.2, “Connecting to common LAN setups”

First, the network cards must be installed and connected to a switch or directly.

Next, check that the network cards are recognized by the kernel, studying the output of the dmesg command. In the following example the kernel recognized correctly an NE2000 clone:

...
ne0 at isa0 port 0x280-0x29f irq 9
ne0: NE2000 Ethernet
ne0: Ethernet address 00:c2:dd:c1:d1:21
...

The following command shows the network card's current configuration:

# ifconfig ne0
ne0: flags=8822<BROADCAST,NOTRAILERS,SIMPLEX,MULTICAST> mtu 1500
address: 00:50:ba:aa:a7:7f
media: Ethernet autoselect (10baseT)
inet6 fe80::250:baff:feaa:a77f%ne0 prefixlen 64 scopeid 0x1 

The software configuration of the network card is very easy. The IP address 192.168.1.1 is assigned to the card.

# ifconfig ne0 inet 192.168.1.1 netmask 0xffffff00

Note that the networks 10.0.0.0/8 and 192.168.0.0/16 are reserved for private networks, which is what we're setting up here.

Repeating the previous command now gives a different result:

# ifconfig ne0
ne0: flags=8863<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST> mtu 1500
address: 00:50:ba:aa:a7:7f
media: Ethernet autoselect (10baseT)
inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255
inet6 fe80::250:baff:feaa:a77f%ne0 prefixlen 64 scopeid 0x1 

The output of ifconfig has now changed: the IP address is now printed and there are two new flags, UP and RUNNING If the interface isn't UP, it will not be used by the system to send packets.

The host was given the IP address 192.168.1.1, which belongs to the set of addresses reserved for internal networks which are not reachable from the Internet. The configuration is finished and must now be tested; if there is another active host on the network, a ping can be tried. For example, if 192.168.1.2 is the address of the active host:

# ping 192.168.1.2
PING ape (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=1.286 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=255 time=0.649 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=255 time=0.681 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=255 time=0.656 ms
^C
----ape PING Statistics----
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.649/0.818/1.286/0.312 ms

With the current setup, at the next boot it will be necessary to repeat the configuration of the network card. In order to avoid repeating the card's configuration at each boot, add the following lines to /etc/rc.conf:

auto_ifconfig=yes
ifconfig_ne0="inet 192.168.1.1 netmask 0xffffff00" 

In this example the variable ifconfig_ne0 was set because the network card was recognized as ne0 by the kernel; if you are using a different adapter, substitute the appropriate name in place of ne0.

At the next boot the network card will be configured automatically.

If you have a router that is connected to the internet, you can use it as default router, which will handle all your packets. To do so, set defaultroute to the router's IP address in /etc/rc.conf:

defaultroute=192.168.0.254

Be sure to use the default router's IP address instead of name, in case your DNS server is beyond the default router. In that case, the DNS server couldn't be reached to resolve the default router's hostname and vice versa, creating a chicken-and-egg problem.

To reach hosts on your local network, and assuming you really have very few hosts, adjust /etc/hosts to contain the addresses of all the hosts belonging to the internal network. For example:

Example 25.2. /etc/hosts

#
# Host Database
# This file should contain the addresses and aliases
# for local hosts that share this file.
# It is used only for "ifconfig" and other operations
# before the nameserver is started.
#
#
127.0.0.1             localhost
::1                   localhost
#
# RFC 1918 specifies that these networks are "internal".
# 10.0.0.0    10.255.255.255
# 172.16.0.0  172.31.255.255
# 192.168.0.0 192.168.255.255

192.168.1.1   ape.insetti.net ape
192.168.1.2   vespa.insetti.net vespa
192.168.1.0   insetti.net

To configure a machine as DNS client, you need to edit /etc/resolv.conf, and enter the DNS server's address, in addition to an optional domain name that will be appended to hosts with no domain, in order to create a FQDN for resolving. Assuming your DNS server's IP address is 192.168.1.2 and it is setup to serve for "home.net", put the following into /etc/resolv.conf:

# /etc/resolv.conf
domain home.net
nameserver 192.168.1.2

Summing up, to configure the network the following must be done: the network adapters must be installed and physically connected. Next they must be configured (with ifconfig) and, finally, the file /etc/rc.conf must be modified to configure the interface and possibly default router, and /etc/resolv.conf and /etc/nsswitch.conf should be adjusted if DNS should be used. This type of network management is sufficient for small networks without sophisticated needs.

25.4. Connecting to a home/office ISP with PPPoE

Many home/office ISPs use PPP (point to point protocol) to provide Internet access to their clients. NetBSD includes pppoe(4) (PPP over Ethernet) functionality that can be used to connect to a modem which communicates with the ISP, typically not using Ethernet, allowing NetBSD to be used as a gateway on small home and office networks.

We start by configuring the kernel for PPPoE use by bumping the tty queue size. This setting can be made permanent by editing /etc/sysctl.conf:

# sysctl -w kern.tty.qsize=32768

Now, create the interface with ifconfig(8):

# ifconfig pppoe0 create
# ifconfig inet 0.0.0.0 0.0.0.1 down
# ifconfig re0 up
# pppoectl -e re0 pppoe0

We are using our computer's re0 interface to connect to our DSL modem.

Then, configure the PPPoE connection to use our ISP's provided username and password:

# pppoectl pppoe0 myauthproto=pap 'myauthname=XXX' 'myauthsecret=YYY' hisauthproto=none

We are now ready to test a first connection. Since something may be wrong, we will restrict retries for now:

# pppoectl pppoe0 max-auth-failure=1
# ifconfig pppoe0 up
# pppoectl -d pppoe0
pppoe0: state = session
	Session ID: 0x254f
	PADI retries: 0
	PADR retries: 0

This example output shows a working setup. The PPPoE session has been established and is still in use (state = session). We can now check the IP negotiation of PPP:

# ifconfig pppoe0
pppoe0: flags=8851<UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1492
	inet 117.80.111.85 -> 118.5.113.169 netmask 0xff000000
    

We can make the configuration permanent by creating /etc/ifconfig.pppoe0:

Example 25.3. /etc/ifconfig.pppoe0

create
# Mark the physical interface used by this PPPoE interface up
! /sbin/ifconfig re0 up
# Let $int use re0 as its Ethernet interface
! /sbin/pppoectl -e re0 $int
# Configure authentication
! /sbin/pppoectl $int myauthproto=pap 'myauthname=XXX' 'myauthsecret=YYY' hisauthproto=none
# Configure the PPPoE interface itself. These addresses are magic
# meaning we don't care about either address and let the remote
# ppp choose them.
0.0.0.0 0.0.0.1 up

To automatically get a route(8) to the outside world, we use ifwatchd(8). Create the following scripts:

Example 25.4. /etc/ppp/ip-up

#!/bin/sh
/sbin/route add default $5

Example 25.5. /etc/ppp/ip-down

#!/bin/sh
/sbin/route delete default $5

And make them executable by root:

# chmod +x /etc/ppp/ip-up /etc/ppp/ip-down

Now, edit /etc/rc.conf to enable ifwatchd:

ifwatchd=YES
ifwatchd_flags="-u /etc/ppp/ip-up -d /etc/ppp/ip-down pppoe0"

And start the service:

# service ifwatchd start

25.4.1. Configuring a VLAN

A typical PPPoE connection requires a VLAN ID to be set on the external interface. On NetBSD this is accomplished by creating a vlan(4) interface:

# ifconfig vlan0 create
# ifconfig vlan0 vlan 6 vlanif pppoe0

Example 25.6. /etc/ifconfig.vlan0

create
vlan 6 vlanif pppoe0

To ensure that vlan0 is created at the appropriate time, refer to Section 25.7, “Ensuring interfaces are initialized in the correct order”.

25.4.2. Setting up MSS clamping

Some systems behind misconfigured firewalls try to use Path-MTU-Discovery, while their firewall blocks all ICMP messages. This is an illegal, but not uncommon configuration. Typically, remote servers with this configuration are outside of your control, but you might still need to connect to them, e.g. to do your online banking.

Without special care, such systems will not be able to send larger chunks of data to a system connected via PPPoE. But there is a workaround: pretend to not be able to handle large packets, by sending a small MSS (maximum segment size) option during initial TCP handshake.

For connections originating from your PPPoE connected system, this is accomplished by setting the sysctl(8) variable net.inet.tcp.mss_ifmtu to 1, i.e. by adding this to /etc/sysctl.conf:

# Obey interface MTUs when calculating MSS
net.inet.tcp.mss_ifmtu=1

For connections originating from systems behind your PPPoE router, you need to configure MSS clamping in your firewall, like in this example /etc/npf.conf:

procedure "norm4" {
	normalize: "random-id", "max-mss" 1440
}

procedure "norm6" {
	normalize: "random-id", "max-mss" 1420
}

group "external" on "pppoe0" {
	pass stateful out final family inet4 all apply "norm4"
	pass stateful out final family inet6 all apply "norm6"
}

For more information about configuring NPF, see Section 25.5, “Setting up an Internet gateway with NPF”

25.4.3. Obtaining IPv6 addresses via Prefix Delegation

To obtain an IPv6 address, the NetBSD kernel must be configured to accept IPv6 router advertisements with sysctl(8):

# sysctl -w net.inet6.ip6.accept_rtadv=1

This setting can be made permanent by editing /etc/sysctl.conf.

Many ISPs implement IPv6 over PPP via prefix delegation. Prefix Delegation can be configured with dhcpcd(8), for example with this /etc/dhcpcd.conf:

Example 25.7. /etc/dhcpcd.conf

duid
ipv6only
require dhcp_server_identifier
option interface_mtu
noipv6rs
slaac private
interface pppoe0
  option rapid_commit
  ipv6rs
  iaid 1
  ia_na 1
  ia_pd 2/::/64 re1/1

With this configuration, running rtadvd(8) on the re1 interface should be enough to assign IPv6 addresses to clients.

If you still can't get IPv6 working, other things to try are to make sure ipv6-icmpand and dhcpv6 can pass through your firewall.

25.5. Setting up an Internet gateway with NPF

npf(7) (NetBSD Packet Filter) is NetBSD's firewall. It can be used to protect a local network from the dangers of the wider Internet, and can also perform Network Address Translation (NAT) in order to make sure IPv4 packets reach the correct destination computer.

Some usage examples of NPF can be found in the subdirectory /usr/share/examples/npf. Look at the file soho_gw-npf.conf for an example of a configuration for a small home/office gateway.

In order to use NetBSD as a gateway, the packet forwarding sysctl(8) options must be enabled. You can add them to /etc/sysctl.conf.

# sysctl -w net.inet.ip.forwarding=1
net.inet.ip.forwarding = 1
# sysctl -w net.inet6.ip6.forwarding=1
net.inet6.ip6.forwarding = 1

And enable NPF in /etc/rc.conf:

npf=YES

The following configuration performs straightforward NAT, using re0 as the external network and re1 as the internal network interface. If you have multiple internal network interfaces, you might want to bridge them. See Section 25.6, “Setting up a network bridge device”

Example 25.8. /etc/npf.conf

$ext_if = "re0"
$int_if = "re1"
$ext_addrs = { ifaddrs($ext_if) }
$localnet = { 192.168.0.1/24 }

# Allow pings.
alg "icmp"

# Perform IPv4 NAT.
map inet4($ext_if) dynamic $localnet -> inet4($ext_if)

group "external" on $ext_if {
	# Allow all outbound traffic
        pass stateful out all
	# Block all incoming traffic
	block in all
}

group "internal" on $int_if {
	# We trust the internal network.
	pass in final all
	pass out final all
}

group default {
	pass final on lo0 all
	block all
}

Usually, you will want to configure dhcpd(8) so clients are automatically assigned IP addresses in the correct range:

Example 25.9. /etc/dhcpd.conf

subnet 192.168.0.0 netmask 255.255.255.0 {
        option routers 192.168.0.1;
	option domain-name-servers 9.9.9.9;
        option subnet-mask 192.168.0.0;
        range 192.168.0.100 192.168.0.254;
        default-lease-time 604800; # default lease 7 days
}

25.6. Setting up a network bridge device

A bridge can be used to combine different physical networks into one logical network, i.e. connect them at layer 2 of the ISO-OSI model, not at layer 3, which is what a router would do. It can allow multiple network interfaces to be addressed as one. The NetBSD bridge driver provides bridge functionality on NetBSD systems.

25.6.1. Bridge example

In this example two physical networks are going to be combined in one logical network, 192.168.1.0, using a NetBSD bridge. The NetBSD machine which is going to act as bridge has two interfaces, ne0 and ne1, which are each connected to one physical network.

When the system is ready the bridge can be created, this can be done using the brconfig(8) command. First of a bridge interface has to be created. With the following ifconfig(8) command the bridge0 interface will be created:

$ ifconfig bridge0 create

Please make sure that at this point both the ne0 and ne1 interfaces are up. The next step is to add the ne0 and ne1 interfaces to the bridge.

$ brconfig bridge0 add ne0 add ne1 up

This configuration can be automatically set up by creating an /etc/ifconfig.interface file, in this case /etc/ifconfig.bridge0, with the following contents:

create
!brconfig $int add ne0 add ne1 up

Note

In NetBSD 10.0 and later, it will become necessary to use vether instead of tap as a bridge endpoint. vether is unavailable in previous releases.

After setting up the bridge the bridge configuration can be displayed using the brconfig -a command. Remember that if you want to give the bridge machine an IP address you can only allocate an IP address to one of the interfaces which are part of the bridge. A virtual tap(4) interface can also be created and configured as a bridge endpoint, e.g. in /etc/ifconfig.tap0:

Example 25.10. /etc/ifconfig.tap0

create
inet 192.168.0.1 netmask 255.255.255.0
up
!ifconfig bridge0 create
!brconfig bridge0 add $int add ne0 add ne1 up

25.7. Ensuring interfaces are initialized in the correct order

In our previous example Section 25.6, “Setting up a network bridge device”, we created a bridge(4) and tap(4) that are dependent upon other networking interfaces to function. This can present a problem if rc(8) initializes them before the interfaces they depend upon. Fortunately, it is possible to force a specific initialization order in /etc/rc.conf:

auto_ifconfig=NO
net_interfaces="ne0 ne1 pppoe0 bridge0 tap0"

With these lines, /etc/ifconfig.ne0 will be read first, and /etc/ifconfig.tap0 last. The same applies if ifconfig_ne0="up" lines are used in /etc/rc.conf instead of dedicated configuration files.

25.8. Some useful commands

The following commands can be useful for diagnosing problems:

ifconfig(8)

Displays and can change the configuration of network intefaces.

ping(8)

Attempt to reach a host and measure latency.

netstat(1)

Displays active connections.

npfctl(8)

npfctl show displays the current firewall configuration, npfctl validate filename can be used to verify a configuration is correct before loading it.

route(8)

route show displays the routing tables, other commands can be used to manipulate them.

traceroute(8)

Shows the route followed by the packets to their destination.

sysstat(1)

sysstat ifstat can be used to monitor network interfaces.

tcpdump(8)

Can be used to monitor TCP/IP traffic.