about summary refs log tree commit diff
path: root/modules/nixos/shadowsocks.nix
blob: b59359ce3ae315b91102f1adcd43deb35418ff79 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
{
  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 <ADDR>: 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";
    };
  };
}

Consider giving Nix/NixOS a try! <3