Loading nixos/modules/services/networking/wstunnel.nix +251 −239 Original line number Diff line number Diff line { config , lib , pkgs , ... { config, lib, pkgs, ... }: let Loading Loading @@ -29,8 +30,7 @@ let package = lib.mkPackageOption pkgs "wstunnel" { }; autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // { autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // { default = true; }; Loading Loading @@ -75,7 +75,9 @@ let }; }; serverSubmodule = { config, ... }: { serverSubmodule = { config, ... }: { options = commonOptions // { listen = lib.mkOption { description = '' Loading @@ -102,10 +104,12 @@ let ''; type = lib.types.listOf (lib.types.submodule hostPortSubmodule); default = [ ]; example = [{ example = [ { host = "127.0.0.1"; port = 51820; }]; } ]; }; enableHTTPS = lib.mkOption { Loading Loading @@ -146,7 +150,9 @@ let }; }; clientSubmodule = { config, ... }: { clientSubmodule = { config, ... }: { options = commonOptions // { connectTo = lib.mkOption { description = "Server address and port to connect to."; Loading Loading @@ -270,22 +276,25 @@ let in { description = "wstunnel server - ${name}"; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = lib.optional serverCfg.autoStart "multi-user.target"; environment.RUST_LOG = serverCfg.loggingLevel; serviceConfig = { Type = "exec"; EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile; EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile; DynamicUser = true; SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group; SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group; PrivateTmp = true; AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; NoNewPrivileges = true; RestrictNamespaces = "uts ipc pid user cgroup"; ProtectSystem = "strict"; Loading @@ -305,19 +314,16 @@ let script = with serverCfg; '' ${lib.getExe package} \ server \ ${lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { ${ lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { restrict-to = map hostPortToString restrictTo; tls-certificate = if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}"; tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}"; } extraArgs )} \ tls-certificate = if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}"; tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}"; } extraArgs ) } \ ${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"} ''; }; Loading @@ -327,21 +333,26 @@ let name = "wstunnel-client-${name}"; value = { description = "wstunnel client - ${name}"; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = lib.optional clientCfg.autoStart "multi-user.target"; environment.RUST_LOG = clientCfg.loggingLevel; serviceConfig = { Type = "exec"; EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile; EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile; DynamicUser = true; PrivateTmp = true; AmbientCapabilities = (lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]); (lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]); NoNewPrivileges = true; RestrictNamespaces = "uts ipc pid user cgroup"; ProtectSystem = "strict"; Loading @@ -361,9 +372,9 @@ let script = with clientCfg; '' ${lib.getExe package} \ client \ ${lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { ${ lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { local-to-remote = localToRemote; remote-to-local = remoteToLocal; http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders; Loading @@ -374,9 +385,9 @@ let tls-verify-certificate = tlsVerifyCertificate; websocket-ping-frequency-sec = websocketPingInterval; http-upgrade-credentials = upgradeCredentials; } extraArgs )} \ } extraArgs ) } \ ${lib.escapeShellArg connectTo} ''; }; Loading @@ -399,10 +410,12 @@ in enableHTTPS = true; tlsCertificate = "/var/lib/secrets/fullchain.pem"; tlsKey = "/var/lib/secrets/key.pem"; restrictTo = [{ restrictTo = [ { host = "127.0.0.1"; port = 51820; }]; } ]; }; }; }; Loading @@ -429,40 +442,39 @@ in config = lib.mkIf cfg.enable { systemd.services = (lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) // (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients)); (lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) // (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients)); assertions = (lib.mapAttrsToList (name: serverCfg: { assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null); (lib.mapAttrsToList (name: serverCfg: { assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null); message = '' Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive. ''; }) cfg.servers) ++ }) cfg.servers) ++ (lib.mapAttrsToList (name: serverCfg: { (lib.mapAttrsToList (name: serverCfg: { assertion = (serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) || (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null); (serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) || (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null); message = '' services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together. ''; }) cfg.servers) ++ }) cfg.servers) ++ (lib.mapAttrsToList (name: clientCfg: { (lib.mapAttrsToList (name: clientCfg: { assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]); message = '' Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set. ''; }) cfg.clients); }) cfg.clients); }; meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ]; meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ]; } nixos/tests/wstunnel.nix +25 −28 Original line number Diff line number Diff line Loading @@ -60,18 +60,15 @@ in clients.my-client = { autoStart = false; connectTo = "wss://${domain}:443"; localToRemote = [ "tcp://8080:localhost:2080" ]; remoteToLocal = [ "tcp://2081:localhost:8081" ]; localToRemote = [ "tcp://8080:localhost:2080" ]; remoteToLocal = [ "tcp://2081:localhost:8081" ]; }; }; }; }; testScript = /* python */ '' testScript = # python '' start_all() server.wait_for_unit("wstunnel-server-my-server.service") client.wait_for_open_port(443, "10.0.0.1") Loading pkgs/by-name/ws/wstunnel/package.nix +24 −13 Original line number Diff line number Diff line { lib , fetchFromGitHub , rustPlatform , testers , wstunnel , nixosTests { lib, fetchFromGitHub, rustPlatform, nixosTests, nix-update-script, versionCheckHook, }: let version = "9.7.4"; version = "10.0.1"; in rustPlatform.buildRustPackage { Loading @@ -18,27 +19,37 @@ rustPlatform.buildRustPackage { owner = "erebe"; repo = "wstunnel"; rev = "v${version}"; hash = "sha256-OFm0Jk06Mxzr4F7KrMBGFqcDSuTtrMvBSK99bbOgua4="; hash = "sha256-lahuuVc+fbuWMXaWvt8C6j26Mo/1o5PkBfVH+lemdv4="; }; cargoHash = "sha256-JMRcXuw6AKfwViOgYAgFdSwUeTo04rEkKj+t+W8wjGI="; cargoHash = "sha256-gNx01LHIcAbedO2X/OwwnQWd9d0Qc6ahe84IRUyptcY="; nativeBuildInputs = [ versionCheckHook ]; doInstallCheck = true; checkFlags = [ # Tries to launch a test container "--skip=tcp::tests::test_proxy_connection" "--skip=protocols::tcp::server::tests::test_proxy_connection" ]; passthru.tests = { version = testers.testVersion { package = wstunnel; }; passthru = { updateScript = nix-update-script { }; tests = { nixosTest = nixosTests.wstunnel; }; }; meta = { description = "Tunnel all your traffic over Websocket or HTTP2 - Bypass firewalls/DPI"; homepage = "https://github.com/erebe/wstunnel"; changelog = "https://github.com/erebe/wstunnel/releases/tag/v${version}"; license = lib.licenses.bsd3; maintainers = with lib.maintainers; [ rvdp neverbehave ]; maintainers = with lib.maintainers; [ rvdp neverbehave ]; mainProgram = "wstunnel"; }; } Loading
nixos/modules/services/networking/wstunnel.nix +251 −239 Original line number Diff line number Diff line { config , lib , pkgs , ... { config, lib, pkgs, ... }: let Loading Loading @@ -29,8 +30,7 @@ let package = lib.mkPackageOption pkgs "wstunnel" { }; autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // { autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // { default = true; }; Loading Loading @@ -75,7 +75,9 @@ let }; }; serverSubmodule = { config, ... }: { serverSubmodule = { config, ... }: { options = commonOptions // { listen = lib.mkOption { description = '' Loading @@ -102,10 +104,12 @@ let ''; type = lib.types.listOf (lib.types.submodule hostPortSubmodule); default = [ ]; example = [{ example = [ { host = "127.0.0.1"; port = 51820; }]; } ]; }; enableHTTPS = lib.mkOption { Loading Loading @@ -146,7 +150,9 @@ let }; }; clientSubmodule = { config, ... }: { clientSubmodule = { config, ... }: { options = commonOptions // { connectTo = lib.mkOption { description = "Server address and port to connect to."; Loading Loading @@ -270,22 +276,25 @@ let in { description = "wstunnel server - ${name}"; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = lib.optional serverCfg.autoStart "multi-user.target"; environment.RUST_LOG = serverCfg.loggingLevel; serviceConfig = { Type = "exec"; EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile; EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile; DynamicUser = true; SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group; SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group; PrivateTmp = true; AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; NoNewPrivileges = true; RestrictNamespaces = "uts ipc pid user cgroup"; ProtectSystem = "strict"; Loading @@ -305,19 +314,16 @@ let script = with serverCfg; '' ${lib.getExe package} \ server \ ${lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { ${ lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { restrict-to = map hostPortToString restrictTo; tls-certificate = if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}"; tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}"; } extraArgs )} \ tls-certificate = if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}"; tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}"; } extraArgs ) } \ ${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"} ''; }; Loading @@ -327,21 +333,26 @@ let name = "wstunnel-client-${name}"; value = { description = "wstunnel client - ${name}"; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; requires = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = lib.optional clientCfg.autoStart "multi-user.target"; environment.RUST_LOG = clientCfg.loggingLevel; serviceConfig = { Type = "exec"; EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile; EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile; DynamicUser = true; PrivateTmp = true; AmbientCapabilities = (lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]); (lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]); NoNewPrivileges = true; RestrictNamespaces = "uts ipc pid user cgroup"; ProtectSystem = "strict"; Loading @@ -361,9 +372,9 @@ let script = with clientCfg; '' ${lib.getExe package} \ client \ ${lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { ${ lib.cli.toGNUCommandLineShell { } ( lib.recursiveUpdate { local-to-remote = localToRemote; remote-to-local = remoteToLocal; http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders; Loading @@ -374,9 +385,9 @@ let tls-verify-certificate = tlsVerifyCertificate; websocket-ping-frequency-sec = websocketPingInterval; http-upgrade-credentials = upgradeCredentials; } extraArgs )} \ } extraArgs ) } \ ${lib.escapeShellArg connectTo} ''; }; Loading @@ -399,10 +410,12 @@ in enableHTTPS = true; tlsCertificate = "/var/lib/secrets/fullchain.pem"; tlsKey = "/var/lib/secrets/key.pem"; restrictTo = [{ restrictTo = [ { host = "127.0.0.1"; port = 51820; }]; } ]; }; }; }; Loading @@ -429,40 +442,39 @@ in config = lib.mkIf cfg.enable { systemd.services = (lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) // (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients)); (lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) // (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients)); assertions = (lib.mapAttrsToList (name: serverCfg: { assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null); (lib.mapAttrsToList (name: serverCfg: { assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null); message = '' Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive. ''; }) cfg.servers) ++ }) cfg.servers) ++ (lib.mapAttrsToList (name: serverCfg: { (lib.mapAttrsToList (name: serverCfg: { assertion = (serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) || (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null); (serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) || (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null); message = '' services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together. ''; }) cfg.servers) ++ }) cfg.servers) ++ (lib.mapAttrsToList (name: clientCfg: { (lib.mapAttrsToList (name: clientCfg: { assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]); message = '' Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set. ''; }) cfg.clients); }) cfg.clients); }; meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ]; meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ]; }
nixos/tests/wstunnel.nix +25 −28 Original line number Diff line number Diff line Loading @@ -60,18 +60,15 @@ in clients.my-client = { autoStart = false; connectTo = "wss://${domain}:443"; localToRemote = [ "tcp://8080:localhost:2080" ]; remoteToLocal = [ "tcp://2081:localhost:8081" ]; localToRemote = [ "tcp://8080:localhost:2080" ]; remoteToLocal = [ "tcp://2081:localhost:8081" ]; }; }; }; }; testScript = /* python */ '' testScript = # python '' start_all() server.wait_for_unit("wstunnel-server-my-server.service") client.wait_for_open_port(443, "10.0.0.1") Loading
pkgs/by-name/ws/wstunnel/package.nix +24 −13 Original line number Diff line number Diff line { lib , fetchFromGitHub , rustPlatform , testers , wstunnel , nixosTests { lib, fetchFromGitHub, rustPlatform, nixosTests, nix-update-script, versionCheckHook, }: let version = "9.7.4"; version = "10.0.1"; in rustPlatform.buildRustPackage { Loading @@ -18,27 +19,37 @@ rustPlatform.buildRustPackage { owner = "erebe"; repo = "wstunnel"; rev = "v${version}"; hash = "sha256-OFm0Jk06Mxzr4F7KrMBGFqcDSuTtrMvBSK99bbOgua4="; hash = "sha256-lahuuVc+fbuWMXaWvt8C6j26Mo/1o5PkBfVH+lemdv4="; }; cargoHash = "sha256-JMRcXuw6AKfwViOgYAgFdSwUeTo04rEkKj+t+W8wjGI="; cargoHash = "sha256-gNx01LHIcAbedO2X/OwwnQWd9d0Qc6ahe84IRUyptcY="; nativeBuildInputs = [ versionCheckHook ]; doInstallCheck = true; checkFlags = [ # Tries to launch a test container "--skip=tcp::tests::test_proxy_connection" "--skip=protocols::tcp::server::tests::test_proxy_connection" ]; passthru.tests = { version = testers.testVersion { package = wstunnel; }; passthru = { updateScript = nix-update-script { }; tests = { nixosTest = nixosTests.wstunnel; }; }; meta = { description = "Tunnel all your traffic over Websocket or HTTP2 - Bypass firewalls/DPI"; homepage = "https://github.com/erebe/wstunnel"; changelog = "https://github.com/erebe/wstunnel/releases/tag/v${version}"; license = lib.licenses.bsd3; maintainers = with lib.maintainers; [ rvdp neverbehave ]; maintainers = with lib.maintainers; [ rvdp neverbehave ]; mainProgram = "wstunnel"; }; }