summaryrefslogtreecommitdiff
path: root/modules/shadowsocks.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/shadowsocks.nix')
-rw-r--r--modules/shadowsocks.nix133
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";
+ };
+ };
+}