# rc.router The FreeBSD Init/RC system could use some extensions for easy configuration of homelab and SOHO routers. These files provide such a set of extensions. These extensions, while providing a lot of advanced functionality, are not meant for anything other than edge routers. "Core router" functionality (which bridges between transit networks) is not provided for by this configuration mechanism. `rc.router` requires FreeBSD-15 or greater. (It might work for some configurations on FreeBSD-14, but I no longer run any routers with it on FreeBSD-14.) ## Mascot Meet "Ricky", the project mascot. ![img](ricky-small.png) I'm no artist, so I had an AI make this. Ricky is a fun little squid made out of the mess of cables in your home network's core. He wants to make your network better! ## Prerequisites None, in particular. The `rc.router/scripts/install-dependencies.sh` script will install all necessary dependency packages for FreeBSD. Several of the `${rc_router_dir}/rc.d` startup scripts depend upon these. It is expected that this script will be run by the administrator to install those packages. ## Directory Layout #### `${rc_router_dir}/rc.d` This directory contains various startup scripts, including configuration file generation scripts. #### `${rc_router_dir}/defaults` This directory contains `rc.conf` defaults which are similar to `/etc/defaults/rc.conf`. This file should not be edited, as user configurations can instead override these default options. #### `${rc_router_dir}/hints` This directory contains configuration hints for various common ISPs. #### `${rc_router_dir}/docs` This directory contains markdown formatted documentation for various `rc.conf` embeddable configuration commands. #### `${rc_router_dir}/templates` This directory contains the base templates for some generated file types. #### `${rc_router_dir}/samples` This directory contains subdirectories with sample configurations for common use cases. Each subdirectory is named for its purpose. The `basic` configuration is recommended as a good starting point. Users should fill in some small details in a "local.conf" file in those configuration samples. When these samples are used, the entire configuration of the router for that purpose should be complete. On next reboot, it should function according to that use case, with no other settings changes necessary. It is recommended that users copy the `sample` configurations as a starting point, rather than modify them in place #### `${rc_router_dir}/harness` This directory contains a testing harness to allow running many of these configuration scripts outside of FreeBSD's init system, for testing and validation. (Use `env RC_ROUTER_HARNESS=${path_to_harness_dir}` to execute one of the `rc.d` scripts or `rc.test`.) ## Installation and Usage The `rc.router` configuration package is designed to be integrated with FreeBSD system startup for use in SOHO and Home-Lab edge routers. It supports easy configuration for automatic generation of a lot of useful components. Eventually the most basic use cases should be as simple as writing just two or three lines of configuration settings. The package is meant to integrate with `/etc/rc.conf` by setting two key variables to help the init system find the package and then by sourcing the package's entry point (`${rc_router_dir}/rc.entry`). One can disable the entire package merely by commenting out that single line which sources `rc.entry`, which provides an easy way to diagnose if this package is causing problems. The `${rc_router_dir}` variable is meant to be set to the root directory of this package, and it must be mounted early enough in the boot process. The `${rc_router_conf_dir}` can be set to any path which will be mounted and present early enough in the boot process as well. The `${rc_router_conf_dir}` can be a git repository where `${rc_router_dir}` is a git submodule therein. This is the recommended deployment strategy, as it permits configuration versioning and easy-to-use rollback semantics for local configuration changes. ## What it does and how it works `rc.router` will setup a number of shell script utility functions for use in processing `rc.conf` style configuration files. After it does this, it will source `${rc_router_conf_dir}/rc.conf`. When it does, the user's preferences for router settings will be processed there. These utility functions simplify the administration of a FreeBSD edge router and firewall by providing easy to use mechanisms to change groups of related `rc.conf` variables for those use cases. For example, instead of having to write: ``` vlans_xy0="2" dhcpd_ifaces="xy0.2" dhcp6c_interfaces="xy0.2" rtadvd_interfaces="xy0.2" ifconfig_xy0_2="192.168.2.1/24" ifconfig_xy0_2_ipv6="fd12:3456:7890:2::1/64" # And manually configure several other related variables and configuration files ``` one could instead just write: ``` add_net xy0 2 ``` and all the necessary `rc.conf` variables will be set by the [`add_net`](docs/add_net.md) command and the related DHCP configuration files and router advertisement configuration files will be generated. Scripts such as `${rc_router_dir}/rc.d/generate_internal_dhcpv4` will generate the necessary configuration files from various `rc.conf` variables and hints. `rc.router` uses several internal variables (set by its commands) to help drive this process, such that more customized configurations can be co-mingled with its patterns. ## Easy setup using the `basic` sample configuration Executing this sequence of sample commands will setup a fully-functional SOHO router using this framework. You'll need to fill in the appropriate choices for your ISP and your network interfaces. ``` $ cd /etc $ mkdir router-conf $ cd router-conf $ git init --object-format=sha256 . $ git submodule add rc.router https://gitea.nerdland.org/rc.router/rc.router $ rc.router/scripts/install-dependencies.sh $ cp rc.router/samples/basic/* . $ cat << EOF > local.conf external_card="abc0" internal_card="xy0" my_isp="verizon_fios" EOF $ git add rc.conf local.conf pf.conf $ git commit -m "FIRST POST!!!" $ echo 'rc_router_dir="/etc/router-conf/rc.router"' >> /etc/rc.conf $ echo 'rc_router_conf_dir="/etc/router-conf"' >> /etc/rc.conf $ echo ". ${rc_router_dir}/rc.entry" >> /etc/rc.conf $ reboot # Router is ready ``` ## How to setup (Easy dual-stack example With Git) Executing this sequence of sample commands will setup a basic Dual-stack router for Verizon FIOS. There are a few pre-canned ISP configuration files which help guide what settings are needed for which ISPs. (Mostly this impacts IPv6 settings not IPv4 settings.) ``` $ cd /etc $ mkdir router-conf $ cd router-conf $ git init --object-format=sha256 . $ cat << EOF > rc.conf # Configure a basic external v4 ISP external_card="em0" add_canned_isp ${external_card} fios_1 verizon_fios # Configure a basic internal v4 network internal_card="re0" add_net ${internal_card} 0 main EOF $ git add rc.conf $ git submodule add rc.router https://gitea.nerdland.org/rc.router/rc.router $ git commit -m "FIRST POST!!!" $ rc.router/scripts/install-dependencies.sh $ echo 'rc_router_dir="/etc/router-conf/rc.router"' >> /etc/rc.conf $ echo 'rc_router_conf_dir="/etc/router-conf"' >> /etc/rc.conf $ echo ". ${rc_router_dir}/rc.entry" >> /etc/rc.conf ``` ## How to setup (Easy v4-only example With Git) Executing this sequence of sample commands will setup a basic v4 NAT/dhcp router. ``` $ cd /etc $ mkdir router-conf $ cd router-conf $ git init --object-format=sha256 . $ cat << EOF > rc.conf # Configure a basic external v4 ISP external_card="em0" add_v4_isp ${external_card} dhcp # Configure a basic internal v4 network internal_card="re0" v4_net="172.26" add_v4_net ${internal_card} 0 main EOF $ git add rc.conf $ git submodule add rc.router https://gitea.nerdland.org/rc.router/rc.router $ git commit -m "FIRST POST!!!" $ rc.router/scripts/install-dependencies.sh $ echo 'rc_router_dir="/etc/router-conf/rc.router"' >> /etc/rc.conf $ echo 'rc_router_conf_dir="/etc/router-conf"' >> /etc/rc.conf $ echo ". ${rc_router_dir}/rc.entry" >> /etc/rc.conf ``` In this example, `em0` will be the uplink card, and will dhcpv4 configure itself. `re0` is the primary internal interface card, which will be configured to host DHCP for internal `172.26.0.0/24` addresses, in the basic default pool of `172.26.0.100` thru `172.26.0.200`. The router's internal address in this subnet is `172.26.0.1/24`. And `8.8.8.8` will be used as the default resolver for everyone within this subnet. ## Interoperation with regular FreeBSD `init` and `rc.conf` configuration These scripts are not meant to replace the FreeBSD init script mechanisms. Instead these scripts seek to augment the system. The scripts provide ways to set clusters of related config variables (and to generate other related configuration files) such that hybrid configurations can be made. The various commands, such as `add_v4_net` result in the setting and updating of various `rc.conf` variables as-if the user simply wrote the correct configuration settings at that point in the `rc.conf` file. As such, these mechanisms are meant to co-exist with manual variable setting and manually maintained configuration files for things such as DHCP. This permits an adoption path other than "big bang cutover". The `rc.router` commands are careful to update-by-append to certain variables, rather than to assume direct ownership of all variables. Thus, `add_net xy0 402` and `ifconfig_xy0_43_alias0="192.168.10.4/24"` could be safely intermingled. (Right now, the scripts assume ownership over specific related variables for interfaces and vlans that they create.) ## IPv6 posture and readiness `rc.router` is designed as an IPv6-first package. While IPv4-only networks are still possible with this package, the defaults are tuned for and assume IPv6. Pre-canned router configurations should gracefully (albeit with some timeouts) fail back to v4-only modes, when IPv6 is not available from those ISPs, due to CPE concerns. IPv6 configuration with `rc.router` permits DHCPv6 `IA_PD` with Router Advertisements or static configuration for the ISP side. For the internal side, SLAAC is the only configuration provided. DHCPv6 internally for `IA_NA` is not implemented. `rc.router` is not expliticly incompatible with DHCPv6 internal provisioning, but no effort has been made to implement or test it. Given that a large number of consumer devices (Android, in particular) refuse to provision via DHCPv6, SLAAC must be used internally for any deployment to accommodate the widest swathe of client devices. `rc.router` installs `tayga` and users are encouraged to use its `map` feature in the configuration file to provide IPv4 addresses for IPv6-only hosts, or vice-versa. This is intended to permit incremental migration for IPv4-only homelabs to dual-stack and IPv6-only deployments. The DHCPv4 configuration generator is capable of emitting Option 108 for IPv6-mostly deployments. .