at 22.05-pre 4.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4let 5 cfg = config.programs.captive-browser; 6in 7{ 8 ###### interface 9 10 options = { 11 programs.captive-browser = { 12 enable = mkEnableOption "captive browser"; 13 14 package = mkOption { 15 type = types.package; 16 default = pkgs.captive-browser; 17 defaultText = literalExpression "pkgs.captive-browser"; 18 description = "Which package to use for captive-browser"; 19 }; 20 21 interface = mkOption { 22 type = types.str; 23 description = "your public network interface (wlp3s0, wlan0, eth0, ...)"; 24 }; 25 26 # the options below are the same as in "captive-browser.toml" 27 browser = mkOption { 28 type = types.str; 29 default = concatStringsSep " " [ 30 ''env XDG_CONFIG_HOME="$PREV_CONFIG_HOME"'' 31 ''${pkgs.chromium}/bin/chromium'' 32 ''--user-data-dir=''${XDG_DATA_HOME:-$HOME/.local/share}/chromium-captive'' 33 ''--proxy-server="socks5://$PROXY"'' 34 ''--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"'' 35 ''--no-first-run'' 36 ''--new-window'' 37 ''--incognito'' 38 ''-no-default-browser-check'' 39 ''http://cache.nixos.org/'' 40 ]; 41 description = '' 42 The shell (/bin/sh) command executed once the proxy starts. 43 When browser exits, the proxy exits. An extra env var PROXY is available. 44 45 Here, we use a separate Chrome instance in Incognito mode, so that 46 it can run (and be waited for) alongside the default one, and that 47 it maintains no state across runs. To configure this browser open a 48 normal window in it, settings will be preserved. 49 50 @volth: chromium is to open a plain HTTP (not HTTPS nor redirect to HTTPS!) website. 51 upstream uses http://example.com but I have seen captive portals whose DNS server resolves "example.com" to 127.0.0.1 52 ''; 53 }; 54 55 dhcp-dns = mkOption { 56 type = types.str; 57 description = '' 58 The shell (/bin/sh) command executed to obtain the DHCP 59 DNS server address. The first match of an IPv4 regex is used. 60 IPv4 only, because let's be real, it's a captive portal. 61 ''; 62 }; 63 64 socks5-addr = mkOption { 65 type = types.str; 66 default = "localhost:1666"; 67 description = "the listen address for the SOCKS5 proxy server"; 68 }; 69 70 bindInterface = mkOption { 71 default = true; 72 type = types.bool; 73 description = '' 74 Binds <package>captive-browser</package> to the network interface declared in 75 <literal>cfg.interface</literal>. This can be used to avoid collisions 76 with private subnets. 77 ''; 78 }; 79 }; 80 }; 81 82 ###### implementation 83 84 config = mkIf cfg.enable { 85 86 programs.captive-browser.dhcp-dns = 87 let 88 iface = prefixes: 89 optionalString cfg.bindInterface (escapeShellArgs (prefixes ++ [ cfg.interface ])); 90 in 91 mkOptionDefault ( 92 if config.networking.networkmanager.enable then 93 "${pkgs.networkmanager}/bin/nmcli dev show ${iface []} | ${pkgs.gnugrep}/bin/fgrep IP4.DNS" 94 else if config.networking.dhcpcd.enable then 95 "${pkgs.dhcpcd}/bin/dhcpcd ${iface ["-U"]} | ${pkgs.gnugrep}/bin/fgrep domain_name_servers" 96 else if config.networking.useNetworkd then 97 "${cfg.package}/bin/systemd-networkd-dns ${iface []}" 98 else 99 "${config.security.wrapperDir}/udhcpc --quit --now -f ${iface ["-i"]} -O dns --script ${ 100 pkgs.writeShellScript "udhcp-script" '' 101 if [ "$1" = bound ]; then 102 echo "$dns" 103 fi 104 ''}" 105 ); 106 107 security.wrappers.udhcpc = { 108 owner = "root"; 109 group = "root"; 110 capabilities = "cap_net_raw+p"; 111 source = "${pkgs.busybox}/bin/udhcpc"; 112 }; 113 114 security.wrappers.captive-browser = { 115 owner = "root"; 116 group = "root"; 117 capabilities = "cap_net_raw+p"; 118 source = pkgs.writeShellScript "captive-browser" '' 119 export PREV_CONFIG_HOME="$XDG_CONFIG_HOME" 120 export XDG_CONFIG_HOME=${pkgs.writeTextDir "captive-browser.toml" '' 121 browser = """${cfg.browser}""" 122 dhcp-dns = """${cfg.dhcp-dns}""" 123 socks5-addr = """${cfg.socks5-addr}""" 124 ${optionalString cfg.bindInterface '' 125 bind-device = """${cfg.interface}""" 126 ''} 127 ''} 128 exec ${cfg.package}/bin/captive-browser 129 ''; 130 }; 131 }; 132}