servo: use ISP-provided DNS resolvers by default
this is really hacky and i hate it, but there's not a lot of good options.
This commit is contained in:
@@ -32,27 +32,66 @@
|
|||||||
# this is needed to forward packets from the VPN to the host
|
# this is needed to forward packets from the VPN to the host
|
||||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||||
|
|
||||||
# we need to use externally-visible nameservers in order for VPNs to be able to resolve hosts.
|
# unless we add interface-specific settings for each VPN, we have to define nameservers globally.
|
||||||
|
# networking.nameservers = [
|
||||||
|
# "1.1.1.1"
|
||||||
|
# "9.9.9.9"
|
||||||
|
# ];
|
||||||
|
|
||||||
|
# use systemd's stub resolver.
|
||||||
|
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
|
||||||
|
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
|
||||||
|
# in the ovnps namespace to use the provider's DNS resolvers.
|
||||||
|
# a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
|
||||||
|
# there also seems to be some cache somewhere that's shared between the two namespaces.
|
||||||
|
# i think this is a libc thing. might need to leverage proper cgroups to _really_ kill it.
|
||||||
|
# - getent ahostsv4 www.google.com
|
||||||
|
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
|
||||||
|
services.resolved.enable = true;
|
||||||
networking.nameservers = [
|
networking.nameservers = [
|
||||||
"1.1.1.1"
|
# use systemd-resolved resolver
|
||||||
"9.9.9.9"
|
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
|
||||||
|
# stub resolver (just forwards upstream) lives on 127.0.0.54
|
||||||
|
"127.0.0.53"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# services.resolved.extraConfig = ''
|
||||||
|
# # docs: `man resolved.conf`
|
||||||
|
# # DNS servers to use via the `wg0` interface.
|
||||||
|
# # i hope that from the root ns, these aren't visible.
|
||||||
|
# DNS=46.227.67.134%wg0 192.165.9.158%wg0
|
||||||
|
# FallbackDNS=1.1.1.1 9.9.9.9
|
||||||
|
# '';
|
||||||
|
|
||||||
# OVPN CONFIG (https://www.ovpn.com):
|
# OVPN CONFIG (https://www.ovpn.com):
|
||||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||||
networking.wireguard.enable = true;
|
networking.wireguard.enable = true;
|
||||||
networking.wireguard.interfaces.wg0 = {
|
networking.wireguard.interfaces.wg0 = let
|
||||||
|
ip = "${pkgs.iproute2}/bin/ip";
|
||||||
|
in-ns = "${ip} netns exec ovpns";
|
||||||
|
# resolvconf = "${pkgs.openresolv}/bin/resolvconf";
|
||||||
|
# ns-setup = pkgs.writeShellScript "ns-setup" ''
|
||||||
|
# # -a <dev> = set DNS for the device <dev>.
|
||||||
|
# # it doesn't ADD a new nameserver: it overwrites any prior DNS settings for the device.
|
||||||
|
# # -m <int> = give the DNS servers a given "metric" (priority?).
|
||||||
|
# printf "nameserver 46.227.67.134\nnameserver 192.165.9.158" \
|
||||||
|
# | ${resolvconf} -a wg0 -m 0
|
||||||
|
# '';
|
||||||
|
in {
|
||||||
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
|
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
|
||||||
# wg is active only in this namespace.
|
# wg is active only in this namespace.
|
||||||
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
|
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
|
||||||
# sudo ip netns exec ovpns ping www.google.com
|
# sudo ip netns exec ovpns ping www.google.com
|
||||||
# note: without the namespace, you'll need to add a specific route through eth0 for the peer (185.157.162.178/32)
|
# note: without the namespace, you'll need to add a specific route through eth0 for the peer (185.157.162.178/32)
|
||||||
# TODO: add DNS here, and then delete the custom bits above
|
# TODO: delete the custom DNS above
|
||||||
# postSetup = ''printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0''
|
# postSetup = ''
|
||||||
|
# # postSetup runs in the original (init) namespace
|
||||||
|
# ${in-ns} ${ns-setup}
|
||||||
|
# '';
|
||||||
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
|
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
|
||||||
interfaceNamespace = "ovpns";
|
interfaceNamespace = "ovpns";
|
||||||
preSetup = "${pkgs.iproute2}/bin/ip netns add ovpns || true";
|
preSetup = "${ip} netns add ovpns || true";
|
||||||
postShutdown = "${pkgs.iproute2}/bin/ip netns delete ovpns";
|
postShutdown = "${ip} netns delete ovpns";
|
||||||
ips = [
|
ips = [
|
||||||
"185.157.162.178/32"
|
"185.157.162.178/32"
|
||||||
];
|
];
|
||||||
@@ -91,6 +130,11 @@
|
|||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
|
|
||||||
ExecStart = let
|
ExecStart = let
|
||||||
|
veth-host-ip = "10.0.1.5";
|
||||||
|
veth-local-ip = "10.0.1.6";
|
||||||
|
vpn-ip = "185.157.162.178";
|
||||||
|
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
|
||||||
|
vpn-dns = "46.227.67.134";
|
||||||
ip = "${pkgs.iproute2}/bin/ip";
|
ip = "${pkgs.iproute2}/bin/ip";
|
||||||
in-ns = "${ip} netns exec ovpns";
|
in-ns = "${ip} netns exec ovpns";
|
||||||
iptables = "${pkgs.iptables}/bin/iptables";
|
iptables = "${pkgs.iptables}/bin/iptables";
|
||||||
@@ -101,34 +145,38 @@
|
|||||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||||
# create veth pair
|
# create veth pair
|
||||||
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
|
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
|
||||||
${ip} addr add 10.0.1.5/24 dev ovpns-veth-a
|
${ip} addr add ${veth-host-ip}/24 dev ovpns-veth-a
|
||||||
${ip} link set ovpns-veth-a up
|
${ip} link set ovpns-veth-a up
|
||||||
|
|
||||||
# mv veth-b into the ovpns namespace
|
# mv veth-b into the ovpns namespace
|
||||||
${ip} link set ovpns-veth-b netns ovpns
|
${ip} link set ovpns-veth-b netns ovpns
|
||||||
${ip} -n ovpns addr add 10.0.1.6/24 dev ovpns-veth-b
|
${ip} -n ovpns addr add ${veth-local-ip}/24 dev ovpns-veth-b
|
||||||
${ip} -n ovpns link set ovpns-veth-b up
|
${ip} -n ovpns link set ovpns-veth-b up
|
||||||
|
|
||||||
# make it so traffic originating from 10.0.1.5 (the root side of the veth)
|
# make it so traffic originating from the host side of the veth
|
||||||
# is sent over the veth no matter its destination.
|
# is sent over the veth no matter its destination.
|
||||||
${ip} rule add from all lookup local pref 100
|
${ip} rule add from all lookup local pref 100
|
||||||
${ip} rule del from all lookup local pref 0
|
${ip} rule del from all lookup local pref 0
|
||||||
${ip} rule add from 10.0.1.5 lookup ovpns pref 50
|
${ip} rule add from ${veth-host-ip} lookup ovpns pref 50
|
||||||
# for traffic originating at 10.0.1.5 to the WAN, use the veth as our gateway
|
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||||
${ip} route add default via 10.0.1.6 dev ovpns-veth-a proto kernel src 10.0.1.5 metric 1002 table ovpns
|
# not sure if the metric 1002 matters.
|
||||||
|
${ip} route add default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns
|
||||||
|
|
||||||
# bridge HTTP traffic:
|
# bridge HTTP traffic:
|
||||||
# any external port-80 request sent to the VPN addr will be forwarded to the rootns.
|
# any external port-80 request sent to the VPN addr will be forwarded to the rootns.
|
||||||
# this exists so LetsEncrypt can procure a cert for the MX over http.
|
# this exists so LetsEncrypt can procure a cert for the MX over http.
|
||||||
# TODO: we could use _acme_challence.mx.uninsane.org CNAME to avoid this forwarding
|
# TODO: we could use _acme_challence.mx.uninsane.org CNAME to avoid this forwarding
|
||||||
# - <https://community.letsencrypt.org/t/where-does-letsencrypt-resolve-dns-from/37607/8>
|
# - <https://community.letsencrypt.org/t/where-does-letsencrypt-resolve-dns-from/37607/8>
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 80 -j DNAT --to-destination 10.0.1.5:80
|
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 80 -j DNAT --to-destination ${veth-host-ip}:80
|
||||||
${in-ns} ${iptables} -A POSTROUTING -t nat -p tcp --dport 80 -j SNAT --to-source 10.0.1.6
|
${in-ns} ${iptables} -A POSTROUTING -t nat -p tcp --dport 80 -j SNAT --to-source ${veth-local-ip}
|
||||||
|
|
||||||
# we also bridge DNS traffic (TODO: figure out why TCP doesn't work. do we need to rewrite the source addr?)
|
# we also bridge DNS traffic (TODO: figure out why TCP doesn't work. do we need to rewrite the source addr?)
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -j DNAT --to-destination 10.0.1.5:53
|
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} -j DNAT --to-destination ${veth-host-ip}:53
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -j DNAT --to-destination 10.0.1.5:53
|
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} -j DNAT --to-destination ${veth-host-ip}:53
|
||||||
# ${in-ns} ${iptables} -A POSTROUTING -t nat -p tcp --dport 53 -j SNAT --to-source 10.0.1.6
|
|
||||||
|
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||||
|
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||||
|
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 -j DNAT --to-destination ${vpn-dns}:53
|
||||||
'';
|
'';
|
||||||
|
|
||||||
ExecStop = with pkgs; writeScript "wg0veth-stop" ''
|
ExecStop = with pkgs; writeScript "wg0veth-stop" ''
|
||||||
|
Reference in New Issue
Block a user