Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550{ lib, pkgs, ... }:let wg-keys = import ./wireguard/snakeoil-keys.nix;
target_host = "acme.test"; server_host = "sing-box.test";
hosts = { "${target_host}" = "1.1.1.1"; "${server_host}" = "1.1.1.2"; }; hostsEntries = lib.mapAttrs' (k: v: { name = v; value = lib.singleton k; }) hosts;
vmessPort = 1080; vmessUUID = "bf000d23-0752-40b4-affe-68f7707a9661"; vmessInbound = { type = "vmess"; tag = "inbound:vmess"; listen = "0.0.0.0"; listen_port = vmessPort; users = [ { name = "sekai"; uuid = vmessUUID; alterId = 0; } ]; }; vmessOutbound = { type = "vmess"; tag = "outbound:vmess"; server = server_host; server_port = vmessPort; uuid = vmessUUID; security = "auto"; alter_id = 0; };
tunInbound = { type = "tun"; tag = "inbound:tun"; interface_name = "tun0"; address = [ "172.16.0.1/30" "fd00::1/126" ]; auto_route = true; iproute2_table_index = 2024; iproute2_rule_index = 9001; route_address = [ "${hosts."${target_host}"}/32" ]; route_exclude_address = [ "${hosts."${server_host}"}/32" ]; strict_route = false; };
tproxyPort = 1081; tproxyPost = pkgs.writeShellApplication { name = "exe"; runtimeInputs = with pkgs; [ iproute2 iptables ]; text = '' ip route add local default dev lo table 100 ip rule add fwmark 1 table 100
iptables -t mangle -N SING_BOX iptables -t mangle -A SING_BOX -d 100.64.0.0/10 -j RETURN iptables -t mangle -A SING_BOX -d 127.0.0.0/8 -j RETURN iptables -t mangle -A SING_BOX -d 169.254.0.0/16 -j RETURN iptables -t mangle -A SING_BOX -d 172.16.0.0/12 -j RETURN iptables -t mangle -A SING_BOX -d 192.0.0.0/24 -j RETURN iptables -t mangle -A SING_BOX -d 224.0.0.0/4 -j RETURN iptables -t mangle -A SING_BOX -d 240.0.0.0/4 -j RETURN iptables -t mangle -A SING_BOX -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A SING_BOX -d ${hosts."${server_host}"}/32 -p tcp -j RETURN iptables -t mangle -A SING_BOX -d ${hosts."${server_host}"}/32 -p udp -j RETURN
iptables -t mangle -A SING_BOX -d ${hosts."${target_host}"}/32 -p tcp -j TPROXY --on-port ${toString tproxyPort} --tproxy-mark 1 iptables -t mangle -A SING_BOX -d ${hosts."${target_host}"}/32 -p udp -j TPROXY --on-port ${toString tproxyPort} --tproxy-mark 1 iptables -t mangle -A PREROUTING -j SING_BOX
iptables -t mangle -N SING_BOX_SELF iptables -t mangle -A SING_BOX_SELF -d 100.64.0.0/10 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 127.0.0.0/8 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 169.254.0.0/16 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 172.16.0.0/12 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 192.0.0.0/24 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 224.0.0.0/4 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 240.0.0.0/4 -j RETURN iptables -t mangle -A SING_BOX_SELF -d 255.255.255.255/32 -j RETURN iptables -t mangle -A SING_BOX_SELF -j RETURN -m mark --mark 1234
iptables -t mangle -A SING_BOX_SELF -d ${hosts."${server_host}"}/32 -p tcp -j RETURN iptables -t mangle -A SING_BOX_SELF -d ${hosts."${server_host}"}/32 -p udp -j RETURN iptables -t mangle -A SING_BOX_SELF -p tcp -j MARK --set-mark 1 iptables -t mangle -A SING_BOX_SELF -p udp -j MARK --set-mark 1 iptables -t mangle -A OUTPUT -j SING_BOX_SELF ''; };in{
name = "sing-box";
meta = { maintainers = with lib.maintainers; [ nickcao ]; };
nodes = { target = { pkgs, ... }: { networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = hosts."${target_host}"; prefixLength = 24; } ]; }; };
services.dnsmasq.enable = true;
services.nginx = { enable = true; package = pkgs.nginxQuic;
virtualHosts."${target_host}" = { onlySSL = true; sslCertificate = ./common/acme/server/acme.test.cert.pem; sslCertificateKey = ./common/acme/server/acme.test.key.pem; http2 = true; http3 = true; http3_hq = false; quic = true; reuseport = true; locations."/" = { extraConfig = '' default_type text/plain; return 200 "$server_protocol $remote_addr"; allow ${hosts."${server_host}"}/32; deny all; ''; }; }; }; };
server = { pkgs, ... }: { boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = 1; };
networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = hosts."${server_host}"; prefixLength = 24; } ]; }; };
systemd.network.wait-online.ignoredInterfaces = [ "wg0" ];
networking.wg-quick.interfaces.wg0 = { address = [ "10.23.42.1/24" ]; listenPort = 2408; mtu = 1500;
inherit (wg-keys.peer0) privateKey;
peers = lib.singleton { allowedIPs = [ "10.23.42.2/32" ];
inherit (wg-keys.peer1) publicKey; };
postUp = '' ${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.23.42.0/24 -o eth1 -j MASQUERADE ''; };
services.sing-box = { enable = true; settings = { inbounds = [ vmessInbound ]; outbounds = [ { type = "direct"; tag = "outbound:direct"; } ]; route = { default_interface = "eth1"; }; }; }; };
tun = { pkgs, ... }: { networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = "1.1.1.3"; prefixLength = 24; } ]; }; };
security.pki.certificates = [ (builtins.readFile ./common/acme/server/ca.cert.pem) ];
environment.systemPackages = [ pkgs.curlHTTP3 pkgs.iproute2 ];
services.sing-box = { enable = true; settings = { inbounds = [ tunInbound ]; outbounds = [ { type = "block"; tag = "outbound:block"; } { type = "direct"; tag = "outbound:direct"; } vmessOutbound ]; route = { default_interface = "eth1"; final = "outbound:block"; rules = [ { inbound = [ "inbound:tun" ]; outbound = "outbound:vmess"; } ]; }; }; }; };
wireguard = { pkgs, ... }: { networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = "1.1.1.4"; prefixLength = 24; } ]; }; };
security.pki.certificates = [ (builtins.readFile ./common/acme/server/ca.cert.pem) ];
environment.systemPackages = [ pkgs.curlHTTP3 pkgs.iproute2 ];
services.sing-box = { enable = true; settings = { outbounds = [ { type = "block"; tag = "outbound:block"; } ]; endpoints = [ { type = "wireguard"; tag = "outbound:wireguard"; name = "wg0"; address = [ "10.23.42.2/32" ]; mtu = 1280; private_key = wg-keys.peer1.privateKey; peers = [ { address = server_host; port = 2408; public_key = wg-keys.peer0.publicKey; allowed_ips = [ "0.0.0.0/0" ]; } ]; system = true; } ]; route = { default_interface = "eth1"; final = "outbound:block"; }; }; }; };
tproxy = { pkgs, ... }: { networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = "1.1.1.5"; prefixLength = 24; } ]; }; };
security.pki.certificates = [ (builtins.readFile ./common/acme/server/ca.cert.pem) ];
environment.systemPackages = [ pkgs.curlHTTP3 ];
systemd.services.sing-box.serviceConfig.ExecStartPost = [ "+${tproxyPost}/bin/exe" ];
services.sing-box = { enable = true; settings = { inbounds = [ { tag = "inbound:tproxy"; type = "tproxy"; listen = "0.0.0.0"; listen_port = tproxyPort; udp_fragment = true; } ]; outbounds = [ { type = "block"; tag = "outbound:block"; } { type = "direct"; tag = "outbound:direct"; } vmessOutbound ]; route = { default_interface = "eth1"; final = "outbound:block"; rules = [ { inbound = [ "inbound:tproxy" ]; outbound = "outbound:vmess"; } ]; }; }; }; };
fakeip = { pkgs, ... }: { networking = { firewall.enable = false; hosts = hostsEntries; useDHCP = false; interfaces.eth1 = { ipv4.addresses = [ { address = "1.1.1.6"; prefixLength = 24; } ]; }; };
environment.systemPackages = [ pkgs.dnsutils ];
services.sing-box = { enable = true; settings = { dns = { final = "dns:default"; independent_cache = true; fakeip = { enabled = true; inet4_range = "198.18.0.0/16"; }; servers = [ { detour = "outbound:direct"; tag = "dns:default"; address = hosts."${target_host}"; } { tag = "dns:fakeip"; address = "fakeip"; } ]; rules = [ { outbound = [ "any" ]; server = "dns:default"; } { query_type = [ "A" "AAAA" ]; server = "dns:fakeip"; } ]; }; inbounds = [ tunInbound ]; outbounds = [ { type = "block"; tag = "outbound:block"; } { type = "direct"; tag = "outbound:direct"; } ]; route = { default_interface = "eth1"; final = "outbound:direct"; rules = [ { action = "sniff"; } { protocol = "dns"; action = "hijack-dns"; } ]; }; }; }; }; };
testScript = '' target.wait_for_unit("nginx.service") target.wait_for_open_port(443) target.wait_for_unit("dnsmasq.service") target.wait_for_open_port(53)
server.wait_for_unit("sing-box.service") server.wait_for_open_port(1080) server.wait_for_unit("wg-quick-wg0.service") server.wait_for_file("/sys/class/net/wg0")
def test_curl(machine, extra_args=""): assert ( machine.succeed(f"curl --fail --max-time 10 --http2 https://${target_host} {extra_args}") == "HTTP/2.0 ${hosts.${server_host}}" ) assert ( machine.succeed(f"curl --fail --max-time 10 --http3-only https://${target_host} {extra_args}") == "HTTP/3.0 ${hosts.${server_host}}" )
with subtest("tun"): tun.wait_for_unit("sing-box.service") tun.wait_for_unit("sys-devices-virtual-net-${tunInbound.interface_name}.device") tun.wait_until_succeeds("ip route get ${hosts."${target_host}"} | grep 'dev ${tunInbound.interface_name}'") tun.succeed("ip addr show ${tunInbound.interface_name}") tun.succeed("ip route show table ${toString tunInbound.iproute2_table_index} | grep ${tunInbound.interface_name}") assert ( tun.succeed("ip rule list table ${toString tunInbound.iproute2_table_index} | sort | head -1 | awk -F: '{print $1}' | tr -d '\n'") == "${toString tunInbound.iproute2_rule_index}" ) test_curl(tun)
with subtest("wireguard"): wireguard.wait_for_unit("sing-box.service") wireguard.wait_for_unit("sys-devices-virtual-net-wg0.device") wireguard.succeed("ip addr show wg0") test_curl(wireguard, "--interface wg0")
with subtest("tproxy"): tproxy.wait_for_unit("sing-box.service") test_curl(tproxy)
with subtest("fakeip"): fakeip.wait_for_unit("sing-box.service") fakeip.wait_for_unit("sys-devices-virtual-net-${tunInbound.interface_name}.device") fakeip.wait_until_succeeds("ip route get ${hosts."${target_host}"} | grep 'dev ${tunInbound.interface_name}'") fakeip.succeed("dig +short A ${target_host} @${target_host} | grep '^198.18.'") '';
}