diff --git a/home/common.nix b/home/common.nix index c2c5264..b8dc67f 100644 --- a/home/common.nix +++ b/home/common.nix @@ -11,6 +11,7 @@ ./modules/packages.nix ./modules/vscodium.nix ./modules/fonts.nix + ./modules/captive-browser.nix ]; home.homeDirectory = if pkgs.stdenv.isDarwin then "/Users/${config.home.username}" else "/home/${config.home.username}"; diff --git a/home/modules/captive-browser.nix b/home/modules/captive-browser.nix new file mode 100644 index 0000000..b07be4c --- /dev/null +++ b/home/modules/captive-browser.nix @@ -0,0 +1,77 @@ +{ + pkgs, + lib, + inputs, + config, + system, + ... +}: + +let + tomlFormat = pkgs.formats.toml { }; + cfg = config.programs.captive-browser; + inherit (pkgs.stdenv.hostPlatform) isDarwin; +in +{ + options.programs.captive-browser = { + enable = lib.mkEnableOption "Enable custom captive-browser in user PATH"; + package = lib.mkPackageOption pkgs "captive-browser" { nullable = true; }; + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = tomlFormat.type; + + options = { + browser = lib.mkOption { + type = lib.types.str; + description = "command to invoke the browser with"; + + # browser is the shell (/bin/sh) command executed once the proxy starts. + # When browser exits, the proxy exits. An extra env var PROXY is available. + # + # Here, we use a separate Chrome instance in Incognito mode, so that + # it can run (and be waited for) alongside the default one, and that + # it maintains no state across runs. To configure this browser open a + # normal window in it, settings will be preserved. + default = '' + ${cfg.browserCommand} \ + --user-data-dir="$HOME/Library/Application Support/Google/Captive" \ + --proxy-server="socks5://$PROXY" \ + --host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost" \ + --no-first-run --new-window --incognito \ + http://example.com + ''; + }; + }; + }; + }; + interface = lib.mkOption { + type = lib.types.str; + description = "WLAN interface to use"; + }; + browserCommand = lib.mkOption { + type = lib.types.str; + default = if isDarwin then "open -n -W -a \"Google Chrome\" --args" else (lib.getExe pkgs.chromium); + }; + }; + config = lib.mkIf cfg.enable { + home.packages = [ cfg.package ]; + + programs.captive-browser.settings = { + # dhcp-dns is the shell (/bin/sh) command executed to obtain the DHCP + # DNS server address. The first match of an IPv4 regex is used. + # IPv4 only, because let's be real, it's a captive portal. + dhcp-dns = "ipconfig getoption ${cfg.interface} domain_name_server"; + + # socks5-addr is the listen address for the SOCKS5 proxy server. + socks5-addr = "localhost:1666"; + }; + home.file.".config/captive-browser.toml" = lib.mkIf (isDarwin && !config.xdg.enable) { + source = tomlFormat.generate "captive-browser-config" cfg.settings; + }; + + xdg.configFile."captive-browser.toml" = lib.mkIf (!(isDarwin && !config.xdg.enable)) { + source = tomlFormat.generate "captive-browser-config" cfg.settings; + }; + + }; +} diff --git a/home/workmac.nix b/home/workmac.nix index f0803ec..0a9cc65 100644 --- a/home/workmac.nix +++ b/home/workmac.nix @@ -93,6 +93,11 @@ in + import ./scripts/ssh-loop-fc.nix { inherit pkgs lib; } ); + # separate proxied browser using the DHCP-supplied DNS for accessing captive portals + programs.captive-browser = { + enable = true; + interface = "en0"; + }; launchd.agents.hydra_proxy = { enable = true; config = {