diff options
author | Azat Bahawi <azat@bahawi.net> | 2024-04-21 02:15:42 +0300 |
---|---|---|
committer | Azat Bahawi <azat@bahawi.net> | 2024-04-21 02:15:42 +0300 |
commit | e6ed60548397627bf10f561f9438201dbba0a36e (patch) | |
tree | f9a84c5957d2cc4fcd148065ee9365a0c851ae1c /modules/shadowsocks.nix | |
parent | 2024-04-18 (diff) |
2024-04-21
Diffstat (limited to 'modules/shadowsocks.nix')
-rw-r--r-- | modules/shadowsocks.nix | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/modules/shadowsocks.nix b/modules/shadowsocks.nix new file mode 100644 index 0000000..670faec --- /dev/null +++ b/modules/shadowsocks.nix @@ -0,0 +1,133 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: +with lib; +let + cfg = config.nixfiles.modules.shadowsocks; +in +{ + options.nixfiles.modules.shadowsocks = { + enable = mkEnableOption "Shadowsocks"; + + port = mkOption { + type = with types; port; + default = 8388; + description = "Port."; + }; + }; + + config = mkIf cfg.enable { + secrets.shadowsocks-json.file = "${inputs.self}/secrets/shadowsocks-json"; + + services.fail2ban.jails.shadowsocks = { + enabled = true; + settings = { + filter = "shadowsocks"; + inherit (cfg) port; + }; + }; + + systemd.services.shadowsocks = { + description = "Shadowsocks"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + RuntimeDirectory = "shadowsocks"; + LoadCredential = "secret.json:${config.secrets.shadowsocks-json.path}"; + ExecStartPre = + let + mergeJson = + let + configFile = pkgs.writeText "config.json" ( + generators.toJSON { } { + server = "::"; + server_port = cfg.port; + # Can't really use AEAD-2022[1] just yet because it's not + # supported by some[2] clients. + # + # [1]: https://shadowsocks.org/doc/sip022.html + # [2]: https://github.com/shadowsocks/ShadowsocksX-NG/issues/1480 + # [2]: https://github.com/shadowsocks/shadowsocks-windows/issues/3448 + # method = "2022-blake3-chacha20-poly1305"; + method = "chacha20-ietf-poly1305"; + password = null; # Must be set as a secret. + users = null; # Muse be set as a secret. + fast_open = true; + acl = pkgs.writeText "block-internal-access.acl" '' + [outbound_block_list] + 0.0.0.0/8 + 10.0.0.0/8 + 100.64.0.0/10 + 127.0.0.0/8 + 169.254.0.0/16 + 172.16.0.0/12 + 192.0.0.0/24 + 192.0.2.0/24 + 192.88.99.0/24 + 192.168.0.0/16 + 198.18.0.0/15 + 198.51.100.0/24 + 203.0.113.0/24 + 224.0.0.0/4 + 240.0.0.0/4 + 255.255.255.255/32 + ::1/128 + ::ffff:127.0.0.1/104 + fc00::/7 + fe80::/10 + ''; + } + ); + in + pkgs.writeShellScript "meregeJson" '' + ${getExe pkgs.jq} \ + -s '.[0] * .[1]' \ + ${configFile} \ + $CREDENTIALS_DIRECTORY/secret.json \ + >$RUNTIME_DIRECTORY/config.json + ''; + in + mergeJson; + ExecStart = "${pkgs.shadowsocks-rust}/bin/ssserver --config \${RUNTIME_DIRECTORY}/config.json"; + }; + }; + + environment.etc = mkIf config.nixfiles.modules.fail2ban.enable { + "fail2ban/filter.d/shadowsocks.conf".text = '' + [Definition] + failregex = ^.*tcp handshake failed.*\[::ffff:<ADDR>\].*$ + ignoreregex = + journalmatch = _SYSTEMD_UNIT=shadowsocks.service + ''; + }; + + networking.firewall.allowedTCPPorts = [ cfg.port ]; + + # https://github.com/shadowsocks/shadowsocks/wiki/Optimizing-Shadowsocks + boot.kernel.sysctl = { + "net.core.rmem_max" = mkOverride 100 (pow 2 26); + "net.core.wmem_max" = mkOverride 100 (pow 2 26); + "net.core.netdev_max_backlog" = pow 2 18; + "net.core.somaxconn" = pow 2 12; + "net.ipv4.tcp_syncookies" = 1; + "net.ipv4.tcp_tw_reuse" = mkOverride 100 1; + "net.ipv4.tcp_tw_recycle" = mkOverride 100 0; + "net.ipv4.tcp_fin_timeout" = mkOverride 100 30; + "net.ipv4.tcp_keepalive_time" = 60 * 20; + "net.ipv4.ip_local_port_range" = "10000 65000"; + "net.ipv4.tcp_max_syn_backlog" = pow 2 13; + "net.ipv4.tcp_max_tw_buckets" = pow 2 12; + "net.ipv4.tcp_fastopen" = mkOverride 100 3; + "net.ipv4.tcp_mem" = mkOverride 100 (mkTcpMem 15 16 17); + "net.ipv4.tcp_rmem" = mkOverride 100 (mkTcpMem 12 16 26); + "net.ipv4.tcp_wmem" = mkOverride 100 (mkTcpMem 12 16 26); + "net.ipv4.tcp_mtu_probing" = 1; + "net.ipv4.tcp_congestion_control" = "hybla"; + }; + }; +} |