diff --git a/hosts/koi/configuration.nix b/hosts/koi/configuration.nix index e3f5d47..1461b55 100755 --- a/hosts/koi/configuration.nix +++ b/hosts/koi/configuration.nix @@ -12,8 +12,8 @@ ./partials/fde.nix - ./services/ss-client.nix ./services/coredns.nix + ./services/sing-box.nix ./services/nginx.nix ./services/landing diff --git a/hosts/koi/containers/sharkey/.config/default.yml b/hosts/koi/containers/sharkey/.config/default.yml index 7a752f5..911051a 100644 --- a/hosts/koi/containers/sharkey/.config/default.yml +++ b/hosts/koi/containers/sharkey/.config/default.yml @@ -31,7 +31,7 @@ clusterLimit: 2 maxNoteLength: 30000 -proxy: 'http://10.42.0.2:7891' +proxy: 'http://10.42.0.2:7890' proxyBypassHosts: - api.deepl.com - api-free.deepl.com diff --git a/hosts/koi/services/sing-box.nix b/hosts/koi/services/sing-box.nix new file mode 100644 index 0000000..e99b24a --- /dev/null +++ b/hosts/koi/services/sing-box.nix @@ -0,0 +1,150 @@ +{ pkgs, abs, config, ... }: + +let + secrets = import (abs "lib/secrets.nix"); +in { + imports = [ + (secrets.declare [ "ss-desu-arm-password" "ss-desu-arm-ip" ]) + ]; + + services.sing-box = { + enable = true; + settings = { + dns = { + rules = [ + { + outbound = [ "any" ]; + server = "dns-coredns"; + } + { + # suffixes specific to our coredns configuration + # we don't want to expose them in the proxy + domain_suffix = [ + ".docker" + ".containers" + ]; + server = "dns-block"; + } + { + rule_set = "rkn"; + query_type = [ "A" "AAAA" ]; + server = "dns-fakeip"; + } + ]; + servers = [ + # upstream dns + { + address = "127.0.0.1"; + tag = "dns-coredns"; + detour = "direct"; + } + { tag = "dns-fakeip"; address = "fakeip"; } + { + tag = "dns-block"; + address = "rcode://success"; + } + ]; + + # "fake ip" setup. + # setup for keenetic: + # 1. create a proxy outbound (see https://help.keenetic.com/hc/ru/articles/7474374790300) + # 2. create a static route for v4, can be done via web ui: Static Routes > Create, Route type = Route to network, + # Destination network address & Subnet mask – from `inet4_range`, interface = [our proxy] + # 3. create a static route for v6, can be done via telnet: `ipv6 route [inet6_range] Proxy0` (interface name may differ) + # 4. set up keenetic to use our dns server: + # 4.1. setup opkg + # 4.2. install dnsmasq + # 4.3. put something along this in /opt/etc/dnsmasq.conf: + # no-resolv + # bind-dynamic + # listen-address=127.0.0.1 + # listen-address=10.42.0.1 + # except-interface=lo + # cache-size=2500 + # port=53 + # + # server=10.42.0.2#5353 # <- ip of the server + # server=8.8.8.8 + # strict-order + # 4.4. run `opkg dns-override` via telnet + # 4.5. set up the router as the only dns server in dhcp settings + fakeip = { + enabled = true; + inet4_range = "10.224.0.0/11"; + inet6_range = "fd3e:dead:dead::/48"; + }; + }; + + inbounds = [ + { + tag = "dns-in"; + type = "direct"; + listen = "0.0.0.0"; + listen_port = 5353; + } + { + tag = "mixed-in"; + type = "mixed"; + listen = "0.0.0.0"; + listen_port = 7890; + } + ]; + + outbounds = [ + { tag = "direct"; type = "direct"; } + { tag = "dns-out"; type = "dns"; } + { + tag = "ss-desu-arm"; + type = "shadowsocks"; + server._secret = config.age.secrets.ss-desu-arm-ip.path; + server_port = 9000; + method = "chacha20-ietf-poly1305"; + password._secret = config.age.secrets.ss-desu-arm-password.path; + udp_over_tcp = { + enabled = true; + version = 1; + }; + } + ]; + + route = { + final = "ss-desu-arm"; + rules = [ + { + inbound = [ "dns-in" ]; + outbound = "dns-out"; + } + { + outbound = "dns-out"; + port = [ 53 ]; + } + ]; + + rule_set = [ + { + tag = "rkn"; + format = "binary"; + + type = "remote"; + url = "https://github.com/teidesu/rkn-singbox/raw/ruleset/rkn-ruleset.srs"; + } + ]; + }; + + experimental = { + cache_file = { + enabled = true; + store_fakeip = true; + }; + + # clash_api = { + # external_controller = "127.0.0.1:9090"; + # external_ui = "dashboard"; + # }; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 7890 ]; + networking.firewall.allowedUDPPorts = [ 5353 ]; +} diff --git a/hosts/koi/services/ss-client.nix b/hosts/koi/services/ss-client.nix deleted file mode 100644 index 2950566..0000000 --- a/hosts/koi/services/ss-client.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ config, abs, pkgs, ... }@inputs: - -let - secrets = import (abs "lib/secrets.nix"); -in -{ - imports = [ - (secrets.declare [ "ss-desu-arm-password" "ss-desu-arm-ip" ]) - ((import (abs "services/shadowsocks-rust.nix") inputs) { - serverFile = config.age.secrets.ss-desu-arm-ip.path; - port = 9000; - passwordFile = config.age.secrets.ss-desu-arm-password.path; - mode = "tcp_and_udp"; - fastOpen = true; - encryptionMethod = "chacha20-ietf-poly1305"; - - client = true; - localPort = 7890; - }) - ]; - - # http -> socks5 proxy - services.privoxy = { - enable = true; - settings = { - listen-address = "0.0.0.0:7891"; - forward-socks5 = "/ 127.0.0.1:7890 ."; - }; - }; - - networking.firewall.allowedTCPPorts = [ 7890 7891 ]; -} diff --git a/services/shadowsocks-rust.nix b/services/shadowsocks-rust.nix deleted file mode 100755 index ed22ce3..0000000 --- a/services/shadowsocks-rust.nix +++ /dev/null @@ -1,88 +0,0 @@ -# Based on https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/networking/shadowsocks.nix - -{ lib, pkgs, ... }: - -with lib; -{ - # Local addresses to which the server binds. - localAddress ? "0.0.0.0" -, # Port which the server uses. - # If `client = true`, port of the remote server to connect to. - port ? 8388 -, # Password for connecting clients - password ? null -, # Password file with a password for connecting clients - passwordFile ? null -, # Relay protocols (one of "tcp_only" "tcp_and_udp" "udp_only") - mode ? "tcp_and_udp" -, # use TCP fast-open - fastOpen ? true -, # Encryption method - encryptionMethod ? "chacha20-ietf-poly1305" -, # SIP003 plugin for shadowsocks - plugin ? null -, # Options to pass to the plugin if one was specified (e.g. "server;host=example.com") - pluginOpts ? "" -, # Whether to set up a Shadowsocks client instead of a server - client ? false -, # Address of the remote Shadowsocks server - server ? null -, # File containing address of the remote Shadowsocks server - serverFile ? null -, # Local port for the client to bind - localPort ? 8388 -, # Additional configuration for shadowsocks that is not covered by the - # provided options. The provided attrset will be serialized to JSON config as-is - extraConfig ? { } -, # Name of the systemd service - serviceName ? "shadowsocks-rust" -, # Shadowsocks-rust package - package ? pkgs.shadowsocks-rust -}: -assert assertOneOf "mode" mode [ "tcp_only" "tcp_and_udp" "udp_only" ]; -assert assertMsg (password == null || passwordFile == null) "Cannot use both password and passwordFile for shadowsocks-rust"; -assert assertMsg (server == null || serverFile == null) "Cannot use both server and serverFile for shadowsocks-rust"; - -let - opts = { - server = localAddress; - server_port = port; - method = encryptionMethod; - mode = mode; - user = "nobody"; - fast_open = fastOpen; - } // optionalAttrs (plugin != null) { - plugin = plugin; - plugin_opts = pluginOpts; - } // optionalAttrs (password != null) { - password = password; - } // optionalAttrs (client == true) { - server = server; - local_address = localAddress; - local_port = localPort; - } // extraConfig; - - configFile = pkgs.writeText "shadowsocks.json" (builtins.toJSON opts); -in -{ - systemd.services.${serviceName} = { - description = "${serviceName} Daemon"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - path = [ package ] ++ optional (plugin != null) plugin ++ optional (passwordFile != null) pkgs.jq; - serviceConfig = { - PrivateTmp = true; - Restart = "on-failure"; - }; - script = '' - cp ${configFile} /tmp/shadowsocks.json - ${optionalString (passwordFile != null) '' - cat /tmp/shadowsocks.json | jq --arg password "$(cat "${passwordFile}")" '. + { password: $password }' > /tmp/shadowsocks.json - ''} - ${optionalString (serverFile != null) '' - cat /tmp/shadowsocks.json | jq --arg server "$(cat "${serverFile}")" '. + { server: $server }' > /tmp/shadowsocks.json - ''} - exec ${if client == true then "sslocal" else "ssserver"} -c /tmp/shadowsocks.json - ''; - }; -}