DNS & DHCP Server – OpenBSD Setup

Set router DHCP to relay

Network Overview

                ┌─────────────────────────────────────────────┐
                │            Router & DHCP relay              │
                │                        ┌───────────────┐    │
                │                        │     Wi‑Fi     │    │
                │                        └──────▲────────┘    │
                └───────▲───────────────────────│─────────────┘
                        │                       │
                        │                       │
                        │                 ┌─────▼───────┐
                ┌───────▼─────────────┐   │ IP Cameras  │
                │  Bridging Firewall  │   │             │
                └───────▲─────────────┘   └─────────────┘
                        │
                        │
                        │
                ┌───────▼───────────────────────────────────────────────────────────┐
                │                                LAN                                │
                │   – Desktops                                                      │
                │   – Laptops                                                       │
                │   – **DNS and DHCP server**                                       │
                │   – NAS (network‑attached storage)                                │
                └───────────────────────────────────────────────────────────────────┘

The router (gateway) is reachable at 192.168.1.1 and new DHCP server will be at 192.168.1.5.

Interface Configuration

/etc/hostname.re0

inet 192.168.1.5 255.255.255.0
    

/etc/mygate

192.168.1.1
    

After editing, reload the network:

# sh /etc/netstart
    

Unbound DNS – Ad‑blocking Setup

  1. Run the script that builds the blocklist: $ ./unbounddnsblock.py
  2. Create the directory for Unbound’s ad‑block config: # mkdir -p /var/unbound/etc/adblock
  3. Copy the generated config file: # cat unboundadblock.conf > /var/unbound/etc/adblock/unboundadblock.conf

/var/unbound/etc/unbound.conf

server:
    interface: 192.168.1.5
    access-control: 192.168.1.0/24 allow
    do-ip6: no
    verbosity: 1
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes
    auto-trust-anchor-file: "/var/unbound/db/root.key"
    prefetch: yes
    include: "/var/unbound/etc/adblock/unboundadblock.conf"
    include: "/var/unbound/etc/lanhosts.conf"

forward-zone:
    name: "."
    forward-addr: 192.168.1.69
#    forward-addr: 1.1.1.1
    

I still have my Pi-hole running, so let's get DNS from there 192.168.1.69

Assigning a local address to an IP
Create /var/unbound/etc/lanhosts.conf file:

    local-zone: "ghr.lan" static
    local-data: "ghr.lan IN A 192.168.1.5"

    local-zone: "pi.hole" static
    local-data: "pi.hole IN A 192.168.1.69"
    

Initialize the trust anchor and test the configuration:

# unbound-anchor -a /var/unbound/db/root.key
$ unbound-checkconf
    

Enable and start Unbound:

# rcctl enable unbound
# rcctl start unbound
    

Check that it’s running:

$ rcctl ls on
    

Test a lookup:

$ dig @192.168.1.5 example.com
    

Log output can be watched with:

$ tail -f /var/log/messages
    

Increase verbosity for more detailed logging

DHCP Server

Copy the example configuration and edit it:

# cp -v /etc/examples/dhcpd.conf /etc/
    

/etc/dhcpd.conf

# Network:              192.168.1.0/255.255.255.0
# Domain name:          ghr.lan
# Name servers:         192.168.1.5
# Default router:       192.168.1.1
# Addresses:            192.168.1.100 - 192.168.1.127
#
option  domain-name "ghr.lan";
option  domain-name-servers 192.168.1.5;

subnet 192.168.1.0 netmask 255.255.255.0 {
        option routers 192.168.1.1;

        range 192.168.1.100 192.168.1.127;
        default-lease-time 604800;
        max-lease-time 2592000;

        host static-client {
                hardware ethernet 22:33:44:55:66:77;
                fixed-address 192.168.1.1;
        }

        host static-client2 {
                hardware ethernet 02:03:04:05:06:07;
                fixed-address 192.168.1.10;
        }

        #add all static clients!
}
    

Enable and start the DHCP daemon

# rcctl enable dhcpd
# rcctl start dhcpd
    

If you modify the config later, restart it:

# rcctl restart dhcpd
    

View active leases:

$ cat /var/db/dhcpd.leases
    

Watch the DHCP log:

$ tail -f /var/log/daemon
    

Internal Web Server (httpd)

# mkdir -p /var/www/htdocs/web
# chmod -R 755 /var/www/htdocs/web
# chown -R www:www /var/www/htdocs/web
    

/etc/httpd.conf

server "default" {
    listen on * port 80
    root "/htdocs/web"
}
    

Start the web server:

# httpd -n
# rcctl enable httpd
# rcctl start httpd
    

Confirm it’s running:

$ rcctl ls on
    

Put index.html to /var/www/htdocs/web/

Packet Filter (pf) Configuration

/etc/pf.conf

eth0 = "re0"

icmp_types = "{ echoreq, unreach }"

set skip on lo

antispoof log quick for $eth0

match in all scrub (no-df max-mss 1440)

block log all

pass in on $eth0 inet proto { tcp udp } from 192.168.1.0/24 to 192.168.1.5 port 53

pass out on $eth0 inet proto tcp to any port { 22 80 443 }
pass in on $eth0 inet proto tcp from 192.168.1.0/24 to any port 22
pass out on $eth0 inet proto udp to any port 123
pass in on $eth0 inet proto udp from 192.168.1.0/24 to any port 123
pass out on $eth0 inet proto { tcp udp } to any port 53

pass on $eth0 inet proto icmp icmp-type $icmp_types

pass in on $eth0 proto tcp from 192.168.1.0/24 to any port 80
    

Bridging firewall pf.conf (old → new)

Old rules

pass out log on $ext_if inet proto udp from 0.0.0.0 port 68 to 255.255.255.255 port 67
pass out log on $ext_if inet proto udp from $localnet port 68 to 192.168.1.1 port 67
pass in log on $ext_if inet proto udp from 192.168.1.1 port 67 to $localnet port 68
    

New rules

pass in log on $ext_if inet proto udp from 0.0.0.0 port 68 to 255.255.255.255 port 67
pass in log on $ext_if inet proto udp from $localnet port 68 to 192.168.1.5 port 67
pass out log on $ext_if inet proto udp from 192.168.1.5 port 67 to $localnet port 68
pass out log on $ext_if inet proto udp from 192.168.1.5 port 67 to 255.255.255.255 port 68
    

In addition, add rules to pass DNS traffic to 192.168.1.5

NTP Server (OpenNTPD)

Add a listen directive to /etc/ntpd.conf

listen on *
    

Restart the daemon. 192.168.1.5 can now be used as a NTP server inside the LAN.

 # rcctl restart ntpd
    
shyster

Author

Heikki Vuojolahti