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