{ pkgs, lib, config, ... }: let ns = "riseup"; dev = "ov-${ns}"; inherit (config.services) openvpn; in { networking.nftables.ruleset = '' add rule inet filter fw2net tcp dport {443,1194} counter accept comment "OpenVPN" ''; systemd.services."openvpn-${ns}" = { bindsTo = [ "netns@${ns}.service" ]; requires = [ "netns@${ns}.service" ]; }; services.openvpn.servers = { "${ns}" = { config = '' verb 3 ca ${riseup/cacert.pem} cert ${riseup/client.pem} client dev ov-${ns} dev-type tun persist-tun nobind # Useless to setup the interface # because moving it to ${ns} will reset it ifconfig-noexec route-noexec persist-key key ${riseup/client.pem} tls-client remote-cert-tls server remote 37.218.241.7 1194 tcp4 remote 37.218.241.106 443 tcp4 remote 163.172.126.44 443 tcp4 remote 198.252.153.28 443 tcp4 remote 199.58.81.143 443 tcp4 remote 199.58.81.145 443 tcp4 remote 212.83.143.67 443 tcp4 remote 212.83.144.12 443 tcp4 remote 212.83.146.228 443 tcp4 remote 212.83.165.160 443 tcp4 remote 212.83.182.127 443 tcp4 remote 212.129.62.247 443 tcp4 reneg-sec 0 script-security 2 up-restart ''; up = let dev = "ov-${ns}"; in '' set -eux PATH=${lib.makeBinPath [pkgs.iproute]} ip link set dev "${dev}" up netns "${ns}" mtu "$tun_mtu" ip netns exec "${ns}" ${pkgs.writeShellScript "route-up.sh" '' set -eux PATH=${lib.makeBinPath [pkgs.iproute pkgs.coreutils]} ip link set dev lo up mkdir -p /etc/netns/"${ns}" foreign_opt_domains= process_foreign_option () { case "$1:$2" in dhcp-option:DNS) echo "nameserver $3" >>/etc/netns/"${ns}"/resolv.conf ;; dhcp-option:DOMAIN) foreign_opt_domains="$foreign_opt_domains $3" ;; esac } if test ! -e /etc/netns/"${ns}"/resolv.conf; then # add DNS settings if given in foreign options i=1 while eval opt=\"\''${foreign_option_$i-}\" [ -n "$opt" ] do process_foreign_option $opt i=$(( i + 1 )) done for d in $foreign_opt_domains; do printf '%s\n' "domain $1" "search $*" \ >>/etc/netns/"${ns}"/resolv.conf done fi netmask4="''${ifconfig_netmask:-30}" netbits6="''${ifconfig_ipv6_netbits:-112}" if [ -n "''${ifconfig_local-}" ]; then if [ -n "''${ifconfig_remote-}" ]; then ip -4 addr replace \ local "$ifconfig_local" \ peer "$ifconfig_remote/$netmask4" \ ''${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"} \ dev "${dev}" else ip -4 addr replace \ local "$ifconfig_local/$netmask4" \ ''${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"} \ dev "${dev}" fi fi if [ -n "''${ifconfig_ipv6_local-}" ]; then if [ -n "''${ifconfig_ipv6_remote-}" ]; then ip -6 addr replace \ local "$ifconfig_ipv6_local" \ peer "$ifconfig_ipv6_remote/$netbits6" \ dev "${dev}" else ip -6 addr replace \ local "$ifconfig_ipv6_local/$netbits6" \ dev "${dev}" fi fi ${pkgs.writeScript "ruleset" openvpn.servers.${ns}.nftables} ''} ''; routeUp = '' set -eux PATH=${lib.makeBinPath [pkgs.iproute]} ${pkgs.coreutils}/bin/env ip netns exec "${ns}" ${pkgs.writeShellScript "route-up.sh" '' set -eux PATH=${lib.makeBinPath [pkgs.iproute]} i=1 while eval net=\"\''${route_network_$i-}\" eval mask=\"\''${route_netmask_$i-}\" eval gw=\"\''${route_gateway_$i-}\" eval mtr=\"\''${route_metric_$i-}\" [ -n "$net" ] do ip -4 route replace "$net/$mask" via "$gw" ''${mtr:+metric "$mtr"} i=$(( i + 1 )) done if [ -n "''${route_vpn_gateway-}" ]; then ip -4 route replace default via "$route_vpn_gateway" fi i=1 while # There doesn't seem to be $route_ipv6_metric_ # according to the manpage. eval net=\"\''${route_ipv6_network_$i-}\" eval gw=\"\''${route_ipv6_gateway_$i-}\" [ -n "$net" ] do ip -6 route replace "$net" via "$gw" metric 100 i=$(( i + 1 )) done # There's no $route_vpn_gateway for IPv6. It's not # documented if OpenVPN includes default route in # $route_ipv6_*. Set default route to remote VPN # endpoint address if there is one. Use higher metric # than $route_ipv6_* routes to give preference to a # possible default route in them. if [ -n "''${ifconfig_ipv6_remote-}" ]; then ip -6 route replace default \ via "$ifconfig_ipv6_remote" metric 200 fi ''} ''; nftables = lib.mkBefore '' #!${pkgs.nftables}/bin/nft -f flush ruleset table inet filter { include "${../../../../var/nftables/filter.txt}" chain input { type filter hook input priority filter policy drop iifname lo accept jump check-tcp ct state { established, related } accept jump accept-connectivity-input jump check-broadcast ct state invalid drop } chain forward { type filter hook forward priority filter policy drop jump accept-connectivity-forward } chain output { type filter hook output priority filter policy drop oifname lo accept ct state { related, established } accept jump accept-connectivity-output } } ''; }; }; }