{ 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-password.file = "${inputs.self}/secrets/shadowsocks-password"; services = { shadowsocks = { enable = true; passwordFile = config.secrets.shadowsocks-password.path; localAddress = ["0.0.0.0"]; mode = "tcp_only"; }; fail2ban.jails.shadowsocks-libev = '' enabled = true filter = shadowsocks-libev port = ${toString cfg.port} ''; }; systemd.services.shadowsocks-libev.path = with pkgs; mkForce [ (writeShellApplication { name = "ss-server"; runtimeInputs = [shadowsocks-libev]; text = let # https://github.com/shadowsocks/shadowsocks-libev/blob/master/acl/server_block_local.acl aclFile = writeText "outbound_block_list.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 '' ss-server --acl ${aclFile} "$@" ''; }) coreutils-full jq ]; environment.etc = mkIf config.nixfiles.modules.fail2ban.enable { "fail2ban/filter.d/shadowsocks-libev.conf".text = '' [Definition] failregex = ^.*failed to handshake with : authentication error$ ignoreregex = journalmatch = _SYSTEMD_UNIT=shadowsocks-libev.service ''; }; networking.firewall = { allowedTCPPorts = [cfg.port]; extraCommands = '' iptables -A nixos-fw -p tcp --syn --dport ${ toString cfg.port } -m connlimit --connlimit-above 32 -j nixos-fw-refuse ''; }; 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" = 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"; }; }; }