Phong Lan


(D240722) Build It Yourself: Alpine Linux Router with PPP DHCP DNS NAT Wi-Fi 4G LTE 5G!

Alpine Linux Router

This guide demonstrates how to set up a simple NAT-box or you may call it a router.

After hours searching on internet, we think there are some articles you may interest:

Why Linux instead of FreeBSD / OpenBSD?

It will be easier to do the job with *BSD but hardware support on Linux is better. The performance was not good on FreeBSD Raspberry Pi 4 last time so.

If you have a hardware that works on *BSD you should go for it, their network stack is pretty rock solid and performant.

PF syntax make more sense to me than nftables, we would stick with FreeBSD if possible.

PF (Packet Filter) and Unbound then you good to go.

Oh good, what next?

A router that performs the following duties:

We will build it from scratch on FriendlyElec NanoPi R2S.

For compatibility you may want x86 instead of ARM, every AMD64 computer with at least 2 NICs should works.

Category Program License Note
OS Alpine Linux VAR
WAN ppp (Paul's PPP Package) BSD PPPoE, cellular network 4G LTE / 5G
DHCP Kea DHCP MPL
DNS Unbound BSD
ROUTE nftables GPL

1. Install OS

For general information you can read on Alpine Linux Wiki.

This is how we did:

2. Config

We install some packages from Alpine store:

Then config them as follow:

1. Interfaces
rabbit:~% cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
        address 192.168.200.1
        netmask 255.255.255.0
        broadcast 192.168.200.255

This Alpine box is under our main router which is running OPNsense.

The box get its dynamic IP from the main router through eth0. You should change it depend on how you get connection from: dhcp, static, ppp..

The box set its static IP on eth1, this address 192.168.200.1 will be the gateway of any devices connect into it (eth1 interface).

For more information, you can read here.

2. DHCP
rabbit:~% cat /etc/kea/kea-dhcp4.conf
# https://kea.readthedocs.io/en/kea-2.6.0/arm/config.html
{
    # DHCPv4 specific configuration.
    "Dhcp4": {
        "interfaces-config": {
            "interfaces": [ "eth1" ],
            "dhcp-socket-type": "raw"
        },
        "valid-lifetime": 4000,
        "renew-timer": 1000,
        "rebind-timer": 2000,
        "subnet4": [{
           "pools": [ { "pool": "192.168.200.20-192.168.200.200" } ],
           "subnet": "192.168.200.0/24",
           "id": 1
        }],

       # Now loggers are inside the DHCPv4 object.
       "loggers": [{
            "name": "*",
            "severity": "DEBUG"
        }],

    # Routing and DNS
    "option-data": [{
        "name": "routers",
        "data": "192.168.200.1"
        },
    {
        "name": "domain-name-servers",
        "data": "192.168.200.1",
        "always-send": true
        }]
    }
}

Kea Configuration Docs is here, you may want to read it.

Don't forget to set routers (routing) and domain-name-servers (DNS), they are important.

3. DNS
rabbit:~% cat /etc/unbound/unbound.conf
server:
  interface: 192.168.200.1
  access-control: 192.168.200.0/24 allow

forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 8.8.4.4

Since we simply want to get DNS from Google, even when Unbound can do better.

3. ip_forward
rabbit:~% cat /etc/sysctl.d/local.conf
# Forward Packets between interfaces
# https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
net.ipv4.ip_forward = 1
net.ipv4.ip_dynaddr = 1

Notes:

4. nftables
rabbit:~% cat /etc/nftables.nft
# Clear all prior state
flush ruleset

# Include modular config files
include "/etc/nftables.d/*.nft"
rabbit:~% cat /etc/nftables.d/rules.nft
define DEV_PRIVATE = eth1
define DEV_WORLD = eth0
define NET_PRIVATE = 192.168.200.0/24

table ip global {

    chain inbound_world {
        # accepting ping (icmp-echo-request) for diagnostic purposes.
        # However, it also lets probes discover this host is alive.
        # This sample accepts them within a certain rate limit:
        #
        icmp type echo-request limit rate 5/second accept

        # allow SSH connections from some well-known internet host
        ip saddr 192.168.100.100 tcp dport ssh accept
    }

    chain inbound_private {
        # accepting ping (icmp-echo-request) for diagnostic purposes.
        icmp type echo-request limit rate 5/second accept

        # allow DHCP, DNS and SSH from the private network
        ip protocol . th dport vmap { tcp . 22 : accept, udp . 53 : accept, tcp . 53 : accept, udp . 67 : accept}
    }

    chain inbound {
        type filter hook input priority 0; policy drop;

        # Allow traffic from established and related packets, drop invalid
        ct state vmap { established : accept, related : accept, invalid : drop }

        # allow loopback traffic, anything else jump to chain for further evaluation
        iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_PRIVATE : jump inbound_private }

        # the rest is dropped by the above policy
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # Allow traffic from established and related packets, drop invalid
        ct state vmap { established : accept, related : accept, invalid : drop }

        # connections from the internal net to the internet or to other
        # internal nets are allowed
        iifname $DEV_PRIVATE accept

        # the rest is dropped by the above policy
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        # masquerade private IP addresses
        ip saddr $NET_PRIVATE oifname $DEV_WORLD masquerade
    }
}

Honestly we don't familiar with nftables, we copied it from Simple ruleset for a home router. This is a demo so we didn't put our time on it.

We just wanted to SNAT from LAN to WAN then we can connect to the world.

If you're in serious, you'll need to read their wiki carefully!

How all of them works together?

You may made your DIY router and you wonder why it work?

For example:

NAT-01

NAT-02

Maybe we should SNAT and change eth0 WAN to static IP in this situation, it will be faster than masquerade.

This is how it works in general.

nftables will handle rules, it is like a door. You write the rules, you make the firewall.

And there are techniques those use DNS like unbound, bind or dnsmasq to block unwanted data, you will found them soon!

Other information

Packet filter: PF, netfilter, NPF, IPFW, IPF

Packet flow:

netfilter

pf

Conclusion

We wrote this guide because we wanted to know how to build a router, it may useful when you want to share your internet (4G, 5G) from your custom hardware.

For convenience we continue run OPNsense and you should too.

« Trang trước Trang sau »