This playbook configures a supported Linux system to work as a wireless router.
For LAN connectivity, it can behave as a 2.4Ghz AP, 5GHz AP and wired
switch at the same time, each element being optional. Each
wired/wireless LAN client can communicate with other clients. IPAM is
handled via dnsmasq
, providing DHCP and DNS to all clients. The LAN IP
range and initial reservations are customizable.
WAN connectivity is expected to be provided via an authenticated PPPoE
link. iptables
rules control forwarding between the LAN and the
Internet, applying IP masquerading to outgoing traffic. All incoming
traffic is blocked by default, with the exception of responses to
LAN-initiated traffic.
The following image depicts relationships between network elements. The scenario involves a separate ONT for FTTH connectivity, which handles the server-side part of PPPoE.
Once configured, the target system should be able to dial a PPP connection, assign addresses to WiFi/wired clients, and handle outgoing NAT'd communications, just like a residential router would.
WARNING: since this playbook configures radio devices, you should read the full documentation before trying to run it. Misconfiguring the WiFi regulatory domain may result in generating interferences with other equipment, and is illegal in many countries.
At the moment, some of the limitations of the playbook are:
- It can only configure a Debian 10/11/12 system; it may work with other Debian versions or derivatives, but this has not been tested;
- No UI for configuration; tweaks must be applied via the command line (e.g., forwarding ports);
It doesn't handle more than one wired NIC (although multiple wired clients can be connected simply by attaching an L2 switch to the NIC configured for wired connectivity)This no longer applies. Variableswired_lan_interface_mac
andwired_lan_interface_name
have been replaced by thewired_lan_interfaces
array, where each entry provides aname
and amac
;- Tweaking AP settings requires editing
hostapd
configuration files within the playbook itself; - Fixed structure for WAN connectivity;
- IPv6 is completely disabled.
ansible/routerify.yaml
contains the plays, which simply call on roles
from ansible/roles/
. Almost all configuration is done via Ansible
variables. Most of them are kept within the defaults
of the role to
which they pertain logically. A few variables that did not fit nicely
in any roles were placed in ansible/group_vars/all/00-defaults.yaml
.
Thus, the simplest way to configure your setup is to add an extra file
under ansible/group_vars/all
that comes lexicographically after the
defaults, and use it to override both globals and role defaults.
Currently, some configuration facets require editing role templates. An
example of this is the hostapd
configuration. Changing the SSID
or the AP channel can be done via variables, but lower-level settings
can only be changed by editing the files.
- Install a base Debian 10/11/12 system. There are no particular
constraints, so you can partition the disks as you like, and install
any additional tools that you want. If you plan to run the playbook on
the system itself, Ansible must be installed. If a remote controller
is used,
ssh
access must be granted. Also,sudo
must be installed, as it's the default privilege escalation method used by Ansible; - Configure the playbook according to your setup, via Ansible variables and template files when needed;
- Run the playbook;
- Reboot the system to apply the new configuration.
A minimal configuration file would look like this:
# SSID used for both 2.4GHz and 5GHz networks, 2.4GHz
# will get a "-24" suffix
ap_common_ssid: MY_SSID
# WARNING: set this according to your local regulations
ap_common_country: IT
# WPA password used for both 2.4GHz and 5GHz networks
ap_common_wifi_password: I_@m_s3cuR3
# Replace all MAC's with the real addresses of the
# devices you want to use
ap24_interface_mac: 01:02:03:04:05:06
ap5_interface_mac: 01:02:03:04:05:07
wired_lan_interfaces:
- mac: 01:02:03:04:05:08
name: lanusb
- mac: 01:02:03:04:05:0A
name: lanpcie
wan_interface_mac: 01:02:03:04:05:09
# Channel selection
ap24_channel: 6
ap5_channel: 36
# IP assignment
lan_bridge_ip: 10.0.1.1/24
lan_bridge_dhcp_range_start: 10.0.1.100
lan_bridge_dhcp_range_end: 10.0.1.199
# Add Google DNS server to the resolver configuration
lan_bridge_extra_nameservers:
- 8.8.8.8
# PPP authentication
wan_chap_username: 'my_username'
wan_chap_password: 'my_password'
The following variables control global execution:
run_handlers
: will force any Ansible handler to run again. This is mainly useful in case an error occurs and the playbook must be re-executed. It ensures that handlers are not skipped because their triggering tasks have already been executed;keep_going
: does not stop on errors. Useful for debugging.reconfigure_now
: defaults tono
and controls service restarting when configuration changes (i.e. iptables rules are changed or PPP credentials are updated). By default, when a configuration file is updated, the corresponding service is not restarted, as that could make the machine unreachable or drop connectivity. Instead, the system keeps using the previous settings and the new configuration is applied during the next boot. If set toyes
, all changes are applied immediately.
A set of variables enable or disable optional features:
enable_rtl8812bu
: if set totrue
, the playbook will install the out-of-tree driver for the Realtek RTL8812BU wireless chipset via DMKS;enable_rtl8821ce
: if set totrue
, the playbook will install the out-of-tree driver for the Realtek RTL8821CE wireless chipset via DMKS;enable_ap5
: if set totrue
, support for a single 5GHz AP is configured;enable_ap24
: if set totrue
, support for a single 2.4GHz AP is configured;enable_wired_lan
: if set totrue
, support for wired LAN connectivity is configured;enable_powersave
: if set totrue
, power-saving configurations will be performed;enable_unattended_upgrades
: if set totrue
, enables daily system updates.
By default, all of the feature variables above are enabled but
enable_rtl8821ce
.
Enabled or disabled via enable_rtl8812bu
. Performed by role
rtl8812bu
.
Generally speaking, the playbook is agnostic to the devices used to create wireless AP's or wired LANs; it simply expects the kernel to support them. If this is not the case, drivers/firmware must be installed before running the playbook.
However, routerify
was written to automate a specific deployment
scenario, which involves a well-defined network adapter employing the
Realtek RTL8812BU chipset. Its Linux driver is not in-tree, so it must
be downloaded, added do DKMS, and compiled for each available kernel.
As a convenience, a role to deploy this specific driver was included, so if you happen to have an adapter employing the same chip this will save you the effort of installing it manually. It also includes some nice module option tweaks (e.g., enabling 80MHz channels in 802.11ac mode).
Disable this feature if you are using any other WiFi chip.
Fine-tuning of this feature can be obtained via the variables define in
roles/rtl8812bu/defaults/main.yaml
. In particular, they define the URL
used to download the driver, and the expected naming of the extracted
folder.
It seems that the only way to enable or disable 80MHz channels in
802.11ac mode is via kernel module parameters. hostapd
settings cannot
override those. For this reason, this role has its own VHT flag,
rtl8812bu_vht_enable
, which simply takes whatever value is defined for
ap5_vht_enable
.
It is also possible to control the USB mode of the device (High
Speed/USB 2.0 or Super Speed/USB 3.0). The default is High Speed because
I have had issues with Super Speed mode on my system, but YMMV. Set
rtl8812bu_usb_superspeed
accordingly.
Equivalent to the previous role, but for the RTL8821CE WiFi chipset.
Enabled or disabled via enable_ap24
. Performed by role ap24
.
If enabled, it will configure an instance of hostapd
to start at boot
and to use a WiFi card supporting AP mode as a 2.4GHz AP.
The following variables can be used to configure the AP:
ap24_interface_name
: defines how the interface used for the 2.4GHz AP will be renamed;ap24_interface_mac
: the AP interface is selected by its MAC address in colon format (e.g.,00:11:22:33:44:55
);ap24_channel
: WiFi channel for the AP; default value is6
;ap24_country
: country code used to set the wireless regulatory domain for the AP. If not explicitly overridden, it will use the value ofap_common_country
;ap24_ssid
: SSID of the 2.4GHz network. If not overridden, it will use the value ofap_common_ssid
, with-24
appended;ap24_password
: ASCII WPA/WPA2 passphrase used for authentication. If not overridden, it will use the value ofap_common_wifi_password
.ap24_ht_enable
: if set totrue
, the 2.4GHz AP will advertise and employ HT (802.11n) capabilities, like 40MHz channels;ap24_ht_capabilities
: a set of HT (802.11n) capabilities that should be enabled for the AP device. It is a single string that is obtained by concatenating individual capability names, each one enclosed in square brackets. This syntax is whathostapd
expects. Consulthostapd
's configuration file for a complete list of capabilities;ap24_use_tkip
: enable or disable the weak TKIP algorithm, default isno
.
To discover which capabilities are supported by your device, use iw phy
, then look for your device and search for Capabilities
.
Capabilities look like this:
Capabilities: 0x19ef
RX LDPC
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Mapping the description provided by iw
to hostapd
capability names
should be straightforward with the help of the configuration file.
For each new setup, the only variables which require tweaking are
ap24_interface_mac
, as every adapter will have its own MAC, and
capabilities, to take advantage of your specific hardware features.
Changing the channel may or may not be useful in your environment.
Country code, SSID, and WPA password can be either set to unique values
or shared with the 5GHz AP. In that case, you should override variables
from the ap_common
role instead.
The template file hostapd.conf.j2
may need to be customized if you
need to change low-level device settings.
Enabled or disabled via enable_ap5
. Performed by role ap5
.
If enabled, it will configure an instance of hostapd
to start at boot
and to use a WiFi card supporting AP mode as a 5GHz AP.
The following variables can be used to configure the AP:
ap5_interface_name
: defines how the interface used for the 5GHz AP will be renamed;ap5_interface_mac
: the AP interface is selected by its MAC address in colon format (e.g.,00:11:22:33:44:55
);ap5_channel
: WiFi channel for the AP, default value is36
;ap5_country
: country code used to set the wireless regulatory domain for the AP. If not explicitly overridden, it will use the value ofap_common_country
;ap5_country3
: extra country code byte that controls indoor/outdoor usage of the AP. The default is0x49
, for indoor-only use;ap5_ssid
: SSID of the 5GHz network. If not overridden, it will use the value ofap_common_ssid
;ap5_password
: ASCII WPA/WPA2 passphrase used for authentication. If not overridden, it will use the value ofap_common_wifi_password
.ap5_vht_enable
: if set totrue
, the 5GHz AP will advertise and employ VHT (802.11ac) capabilities, like 80MHz channels;ap5_ht_capabilities
: a set of HT (802.11n) capabilities that should be enabled for the AP device. It is a single string that is obtained by concatenating individual capability names, each one enclosed in square brackets. This syntax is whathostapd
expects. Consulthostapd
's configuration file for a complete list of capabilities.ap5_vht_capabilities
: a set of VHT capabilities that should be enabled for the AP device. It is a single string that is obtained by concatenating individual capability names, each one enclosed in square brackets. This syntax is whathostapd
expects. Consulthostapd
's configuration file for a complete list of capabilities.ap5_use_tkip
: enable or disable the weak TKIP algorithm, default isno
.
To discover which capabilities are supported by your device, use iw phy
, then look for your device and search for Capabilities
or
VHT Capabilities
. Capabilities look like this:
Capabilities: 0x19ef
RX LDPC
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
VHT Capabilities (0x039071f6):
Max MPDU length: 11454
Supported Channel Width: 160 MHz
RX LDPC
short GI (80 MHz)
short GI (160/80+80 MHz)
TX STBC
SU Beamformee
MU Beamformee
Mapping the description provided by iw
to hostapd
capability names
should be straightforward with the help of the configuration file.
For each new setup, the only variables which require tweaking are
ap5_interface_mac
, as every adapter will have its own MAC, and
capabilities, to take advantage of your specific hardware features.
Changing the channel may or may not be useful in your environment.
Country code, SSID and WPA password can be either set to unique values
or shared with the 2.4GHz AP. In that case, you should override
variables from the ap_common
role instead.
The template file hostapd.conf.j2
may need to be customized if you
need to change low-level device settings.
Performed by role ap_common
. This role acts as a dependency, and
cannot be enabled or disabled on its own. It is called by other AP
roles.
# Base SSID used for both 2.4GHz and 5GHz if not overridden
ap_common_ssid: MYSSID
# Global country code
ap_common_country: IT
# Default password shared between bands
ap_common_wifi_password: abcd$1234
# Enable the weaker TKIP pairwise algorithm
ap_common_use_tkip: no
It defines the SSID, country code and password variables, which are
inherited by ap24
and ap5
, unless overridden. It is useful to set
the same configuration for both bands at once.
Enabled or disabled via enable_wired_lan
. Performed by role
wired_lan
.
If enabled, it will configure a set of wired interfaces to join the LAN. Every host can see all other wired/wireless nodes and gets its own address from the local DHCP server.
The following variables can be used:
-
wired_lan_interfaces
: an array of objects giving aname
and amac
. The MAC will be used to match a network interface that will be renamed toname
and enslaved to the LAN bridge. The following snippet can be used to add a USB-to-Ethernet adapter and an internal PCIe card:wired_lan_interfaces: - mac: 01:02:03:04:05:08 name: lanusb - mac: 01:02:03:04:05:0A name: lanpcie
Performed by role lan-bridge
. This role acts as a dependency, and
cannot be enabled or disabled on its own.
It creates a software switch, to which the wired LAN interfaces, the 2.4GHz AP, and the 5GHz AP will connect to allow for hosts to reach one another at L2 level.
The following variables can be used:
-
lan_bridge_interface_name
: the name of the bridge. Must be a valid Linux interface name; -
lan_bridge_ip
: IPv4 assigned to the bridge interface, used to address the router itself. Must be given in CIDR notation (e.g.,10.0.1.1/24
); -
lan_bridge_extra_nameservers
: a list of additional name servers thatdnsmasq
will use to resolve domain names; -
lan_bridge_dhcp_range_start
: this is the first address of the DHCP pool, inclusive (e.g.,10.0.1.100
); -
lan_bridge_dhcp_range_end:
: this is the last address of the DHCP pool, inclusive (e.g.,10.0.1.199
); -
lan_bridge_dhcp_reservations
: this is the list of MAC reservations. Each reservation is an object with amac
and anip
fields:lan_bridge_dhcp_reservations: - mac: "11:22:33:44:55:66" ip: "10.0.1.10"
-
lan_bridge_dhcp_domain
: domain name of the local network; -
lan_bridge_host_aliases
: a map that assigns additional DNS names to specific hosts, for example:lan_bridge_host_aliases: - ip: 192.168.1.10 aliases: - "web.lan" - "printer.lan"
Currently, it is not possible to disable DHCP; however, hosts can still be configured to use static addresses, and the DHCP range can be very small.
lan_bridge_ip
must lay outside the DHCP range. Currently, this is not
checked nor is checked that they are on the same subnet.
Enabled or disabled via enable_powersave
. Performed by role
powersave
.
It configures energy-related settings to ensure that:
- sleep, suspend, and hibernation are disabled;
- the screen shuts down after a timeout while displaying the console.
These settings are mainly useful when a laptop is used as a router. The first bullet ensures that you cannot put the system to sleep by mistake if the lid is closed. The second bullet cuts screen power so that it does not remain on forever.
The following variables can be used:
powersave_tty_poweroff_minutes
: controls the inactivity timeout in minutes; the screen will power off after this set period of time.
Performed by role wan
. This role acts as a dependency, and
cannot be enabled or disabled on its own.
It performs all the required configuration steps to allow a PPP connection to be established between the system and an upstream PPPoE server, via which Internet access is obtained. It involves settings up PPPoE, VLAN tagging, and identifying the physical NIC connected to the ONT.
Currently, this is the only supported scheme for connecting to the Internet. PPPoE must be authenticated with CHAP.
PPPoE connections react to carrier changes of the physical NIC. When the carrier goes away, the connection is terminated. When the carrier is detected, it is brought up.
The following variables can be used:
wan_interface_name
: the final name of the physical NIC connected to the ONT;wan_interface_mac
: MAC of the physical NIC, in:
-separated form;wan_chap_username
: CHAP username;wan_chap_password
: CHAP password;wan_vlan_id
: ID of the VLAN on which PPPoE traffic is sent. This is usually an ISP-provided value;wan_vlan_interface_name
: final name of the VLAN interface;wan_ppp_interface_name
: final name of the PPP interface.
After configuration, the system will route packets as most residential routers would do:
- Outgoing traffic is allowed from both the router itself and from any LAN host, and is subject to masquerading;
- Inbound traffic that is related to already seen outgoing traffic is allowed;
- Establishing new connections from the WAN is not allowed (e.g., all ports are closed).
Before provisioning, the following variables can be used to define port forwarding to specific services:
routing_input_rules
defines ports on the router itself that will be accessible from the Internet (e.g., to allow SSH connectivity from outside the network);routing_portfwd_rules
defines port forwarding rules for services that are offered by hosts behind the gateway itself. You should state both the port and the target host address;routing_other_rules
defines ports on the router itself that will be accessible from any interface which is not the PPP interface (this means that such ports are open for additional, non PPPoE traffic coming from the WAN interface). This is mainly useful if you need to connect to SSH from a local interface which is not part of the LAN.
Have a look at their definitions for the exact layout.
Port forwarding can be enabled by adding new rules/items to dedicated chains/sets, depending on the location of the target service:
-
For services that run on the router itself, simply add the port number you want to open to either
TCPLOCALPORTS
orUDPLOCALPORTS
sets (if you want them to be accessible from the Internet). This is equivalent to a setup-time rule added torouting_input_rules
. UsingTCPOTHERPORTS
orUDPOTHERPORTS
instead is equivalent to usingrouting_other_rules
. For example:# For a TCP service ipset add TCPLOCALPORTS 5000 # For a UDP service ipset add UDPLOCALPORTS 5000 # Make the change persistent ipset save > /etc/iptables/ipsets
-
For services running on a LAN node, define the appropriate DNAT rule, adding it to the
PORTFWD
chain in the NAT table:# DNAT connections for local port 2222/TCP to 192.168.1.100:4444 iptables -t nat -A PORTFWD -p tcp --dport 2222 \ -j DNAT --to-destination 192.168.1.100:4444 # Make the change persistent iptables-save > /etc/iptables/rules.v4
It is also possible to block outgoing Internet traffic from specific
clients by MAC address. Clients whose MACs are listed in
routing_no_internet_clients
will not be able to access the Internet.
The ipset NOINTERNETCLIENTS
contains such MACs anmd can be modified
manually for one-off tests.
Implemented by unattended-upgrades
.
The system is configured to fetch and apply security updates daily at a
specified time. unattended_upgrades_time
controls that time. To avoid
connectivity disruptions, the system is never scheduled for a reboot,
even if it's needed to update the running kernel.
The vagrant
subfolder contains support files to provision a debug
machine that can be used for quick and dirty testing of the playbook. It
is designed to use VirtualBox and USB passthrough to drive real WiFi
adapters in AP mode, while the WAN and LAN interfaces are faked via
host-only networks.
At present, the Vagrantfile
is incomplete. It will try to load ad
additional file called ap_spec.rb
which shall provide information
about the AP devices to use:
AP24_MAC = "11:22:33:44:55:66"
AP24_VID = "1111"
AP24_PID = "2222"
AP5_MAC = "11:22:33:44:55:67"
AP5_VID = "3333"
AP5_PID = "4444"
AP24_PROVISIONER = "./ap24.yaml"
AP5_PROVISIONER = ""
For both the 2.4GHz and 5GHz APs, you should provide their MAC addresses, as well as their USB vendor and product ID (which are needed to automatically setup VirtualBox passthrough filters). Leaving a VID blank will disable the corresponding AP from the playbook execution.
By defining *_PROVISIONER
to point to a file, it will automatically be
invoked as an Ansible playbook prior to running routerify
. This is
optional and useful if your AP device needs additional setup to work
(i.e. firmware files).
The following VM definitions are available:
debian-10
debian-11
debian-12
Each one uses the specified Debian version as the guest system.
While it is possible to manually edit configuration files to tweak an
already configured system, it is just easier to update a YAML file with
variable definitions and re-run the playbook. Ensure to set
reconfigure_now
to yes
so that changes are applied immediately.