at 24.11-pre 4.5 kB view raw
1{ config, 2 lib, 3 pkgs, 4 ... 5}: 6 7let 8 cfg = config.services.microsocks; 9 10 cmd = 11 if cfg.execWrapper != null 12 then "${cfg.execWrapper} ${cfg.package}/bin/microsocks" 13 else "${cfg.package}/bin/microsocks"; 14 args = 15 [ "-i" cfg.ip "-p" (toString cfg.port) ] 16 ++ lib.optionals (cfg.authOnce) [ "-1" ] 17 ++ lib.optionals (cfg.disableLogging) [ "-q" ] 18 ++ lib.optionals (cfg.outgoingBindIp != null) [ "-b" cfg.outgoingBindIp ] 19 ++ lib.optionals (cfg.authUsername != null) [ "-u" cfg.authUsername ]; 20in { 21 options.services.microsocks = { 22 enable = lib.mkEnableOption "Tiny, portable SOCKS5 server with very moderate resource usage"; 23 user = lib.mkOption { 24 default = "microsocks"; 25 description = "User microsocks runs as."; 26 type = lib.types.str; 27 }; 28 group = lib.mkOption { 29 default = "microsocks"; 30 description = "Group microsocks runs as."; 31 type = lib.types.str; 32 }; 33 package = lib.mkPackageOption pkgs "microsocks" {}; 34 ip = lib.mkOption { 35 type = lib.types.str; 36 default = "127.0.0.1"; 37 description = '' 38 IP on which microsocks should listen. Defaults to 127.0.0.1 for 39 security reasons. 40 ''; 41 }; 42 port = lib.mkOption { 43 type = lib.types.port; 44 default = 1080; 45 description = "Port on which microsocks should listen."; 46 }; 47 disableLogging = lib.mkOption { 48 type = lib.types.bool; 49 default = false; 50 description = "If true, microsocks will not log any messages to stdout/stderr."; 51 }; 52 authOnce = lib.mkOption { 53 type = lib.types.bool; 54 default = false; 55 description = '' 56 If true, once a specific ip address authed successfully with user/pass, 57 it is added to a whitelist and may use the proxy without auth. 58 ''; 59 }; 60 outgoingBindIp = lib.mkOption { 61 type = lib.types.nullOr lib.types.str; 62 default = null; 63 description = "Specifies which ip outgoing connections are bound to"; 64 }; 65 authUsername = lib.mkOption { 66 type = lib.types.nullOr lib.types.str; 67 default = null; 68 example = "alice"; 69 description = "Optional username to use for authentication."; 70 }; 71 authPasswordFile = lib.mkOption { 72 type = lib.types.nullOr lib.types.path; 73 default = null; 74 example = "/run/secrets/microsocks-password"; 75 description = "Path to a file containing the password for authentication."; 76 }; 77 execWrapper = lib.mkOption { 78 type = lib.types.nullOr lib.types.str; 79 default = null; 80 example = '' 81 ''${pkgs.mullvad-vpn}/bin/mullvad-exclude 82 ''; 83 description = '' 84 An optional command to prepend to the microsocks command (such as proxychains, or a VPN exclude command). 85 ''; 86 }; 87 }; 88 config = lib.mkIf cfg.enable { 89 assertions = [ 90 { 91 assertion = (cfg.authUsername != null) == (cfg.authPasswordFile != null); 92 message = "Need to set both authUsername and authPasswordFile for microsocks"; 93 } 94 ]; 95 users = { 96 users = lib.mkIf (cfg.user == "microsocks") { 97 microsocks = { 98 group = cfg.group; 99 isSystemUser = true; 100 }; 101 }; 102 groups = lib.mkIf (cfg.group == "microsocks") { 103 microsocks = {}; 104 }; 105 }; 106 systemd.services.microsocks = { 107 enable = true; 108 description = "a tiny socks server"; 109 after = [ "network.target" ]; 110 wantedBy = [ "multi-user.target" ]; 111 serviceConfig = { 112 User = cfg.user; 113 Group = cfg.group; 114 Restart = "on-failure"; 115 RestartSec = 10; 116 LoadCredential = lib.optionalString (cfg.authPasswordFile != null) "MICROSOCKS_PASSWORD_FILE:${cfg.authPasswordFile}"; 117 MemoryDenyWriteExecute = true; 118 SystemCallArchitectures = "native"; 119 PrivateTmp = true; 120 NoNewPrivileges = true; 121 ProtectSystem = "strict"; 122 ProtectHome = true; 123 ProtectKernelModules = true; 124 ProtectKernelTunables = true; 125 PrivateDevices = true; 126 RestrictSUIDSGID = true; 127 RestrictNamespaces = [ 128 "cgroup" 129 "ipc" 130 "pid" 131 "user" 132 "uts" 133 ]; 134 }; 135 script = 136 if cfg.authPasswordFile != null 137 then '' 138 PASSWORD=$(cat "$CREDENTIALS_DIRECTORY/MICROSOCKS_PASSWORD_FILE") 139 ${cmd} ${lib.escapeShellArgs args} -P "$PASSWORD" 140 '' 141 else '' 142 ${cmd} ${lib.escapeShellArgs args} 143 ''; 144 }; 145 }; 146}