This article presents a detailed guide centered around OpenBSD and Linux for enhancing network security through the implementation of dynamic IP filtering, WireGuard VPN configurations, and encrypted DNS services.

It covers initial setups, script-based automation, and firewall configurations to ensure secure, efficient, and scalable network management.

Whether you’re aiming to protect SSH access, secure your VPN connections, or block unwanted ads, this guide offers comprehensive instructions to fortify your network against vulnerabilities.

This project gets you:

  • OpenBSD: Static filtering of static IPs for SSH
  • OpenBSD: Dynamic filtering of dynamic IPs for VPN (Wireguard)
  • Linux: Dynamic filtering of dynamic IPs for VPN (Wireguard)
  • OpenBSD: Encrypted DNS via ODoH / DoT via Unbound + DNScrypt
  • OpenBSD: Adblocker skript to pull adlists for Unbound

Some Steps

  1. Initial Setup: Start by configuring the OpenBSD gateway with the provided PF configuration to set up initial firewall rules.
  2. Dynamic IP Script: Implement the dynamic IP update script to maintain an up-to-date whitelist of IPs that can access the VPN.
  3. Cron Configuration: Schedule the provided cron jobs to automate the updating and maintenance tasks.
  4. DNS Encryption: Follow the DNS setup instructions to encrypt DNS queries, using either DoT or ODoH.
  5. Ad Blocking: Set up the ad blocker script to filter out unwanted ads.

Detailed Configuration Scripts And Commands

  • Dynamic IP Update Script ( This script resolves the current IP address for a specified FQDN and updates the PF table with any changes.
  • PF Configuration (pf.conf): Includes rules for blocking, allowing SSH from specific IPs, handling Wireguard traffic, and default deny policies.
  • Cron Jobs: Automates system updates, VPN renewals, and the dynamic IP update script.
  • DNS Configuration: Setup guides for DoT and ODoH, including configuration changes for dnscrypt-proxy.
  • Ad Blocker Script: Instructions and script for setting up ad blocking on OpenBSD using Unbound.

Some OpenBSD Cronjobs Right Away

  • add via crontab -e
@reboot /bin/sleep 30 && /usr/local/bin/wg-quick up wg0
@reboot /bin/sleep 30 && /usr/sbin/rcctl restart unbound
30 13 * * * /usr/sbin/syspatch -c 
32 13 * * * /usr/sbin/syspatch
35 13 * * * /usr/sbin/pkg_add -u

30 4 * * 3 /usr/local/
0 0 * * * /usr/local/
2 0 * * * /usr/sbin/rcctl restart unbound

Firewall : OpenBSD PF Rules For Static And Dynamic IPS

  • You edit the pf rules on /etc/pf.conf and check via pfctl -nf /etc/pf.conf and load them via pfctl -f /etc/pf.conf
# $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $
# See pf.conf(5) and /etc/examples/pf.conf

# Configuration Variables
dynamic_hosts_file="/usr/local/gotten-para"  # Location for dynamic hosts
wireguard_port="51820"                        # Your WireGuard VPN port
wireguard_net=""                 # Your WireGuard VPN network
ssh_allowed_ips="{,}"  # IPs allowed for SSH
wireguard_iface="wg0"                       # WireGuard interface identifier

# Block Ipv6 - remember hotspot leakage
block quick inet6

set skip on lo

# Block all incoming on vio0 but allow outgoing
block in on vio0 all

# NAT for outgoing traffic
match out on egress inet from !(egress:network) to any nat-to (egress:0)

# Allow SSH from specified IPs
pass in on vio0 proto tcp from $ssh_allowed_ips to (vio0) port 22 keep state
pass out quick on vio0 keep state

# Allow only IPs from <dynamic_hosts> to access WireGuard port on vio0
pass in on vio0 proto udp from <dynamic_hosts> to any port $wireguard_port keep state
pass out on vio0 proto udp to <dynamic_hosts> port $wireguard_port keep state

# Allow all on WireGuard interface
pass in on $wireguard_iface from $wireguard_net to any
pass out on $wireguard_iface from any to $wireguard_net

# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010

# Port build user does not need network
block return out log proto {tcp udp} user _pbuild

Skript To Add The Dynamic Hosts

  • Important: All your clients will need to get FQDNs, and you can do that by adding for example containers in your home, work etc, that use tools like ddclient + any DYNDNS-hoster.
  • Next, Ensure you replace with your actual domain domain.
  • The script below will access the FQDN and add it to the firewall ruletable for access.

I’ve deployed the following script on /usr/local/ it creates temp_gotten_para as well as gotten-para which contains the dynamic IPs to be added to the firewall for access.


# FQDN to resolve

# Variables

# Resolve the current IP address of the FQDN
CURRENT_IP=$(dig +short $FQDN)

# Ensure FINAL_IP_FILE exists
if [ ! -f "$FINAL_IP_FILE" ]; then
    touch "$FINAL_IP_FILE"

# Exit if no IP is resolved
[ -z "$CURRENT_IP" ] && echo "No IP address found for $FQDN" && exit 1

# Append current IP with timestamp to TEMP_IP_FILE for processing

# Process TEMP_IP_FILE to ensure uniqueness, limit the number of IPs, and consider the retention period
awk -v max_count=$MAX_IP_COUNT -v retention_days=$IP_RETENTION_DAYS -v current_time=$CURRENT_TIMESTAMP '{
    ip = $2
    timestamp = $1
    if (!seen[ip]++ && (current_time - timestamp) <= (retention_days * 86400)) {
        print ip
        if (++count >= max_count) exit
}' "$TEMP_IP_FILE" | sort -u | tail -n $MAX_IP_COUNT > "$FINAL_IP_FILE"

# Reload the PF table with the updated IP list
pfctl -t dynamic_hosts -T replace -f "$FINAL_IP_FILE" && echo "pf table reloaded with updated IP list."

For more information click here