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