vpn mode to eww
This commit is contained in:
6 files changed
+90
-16
No files matched your search
@@ -1,5 +1,5 @@
|
|||||||
(deflisten net
|
(deflisten net
|
||||||
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""},"wireguard":[],"vpn":{"up":false,"name":""}}'
|
:initial '{"wifi":{"connected":false,"enabled":false,"icon":"","ssid":"","ip":"","freq":0,"band":"","gen":"","signal":0},"ethernet":{"connected":false,"interface":"","ip":"","speed":""},"usb":{"connected":false,"interface":"","ip":""},"wireguard":[],"vpn":{"up":false,"full":false,"name":""}}'
|
||||||
"scripts/net/net")
|
"scripts/net/net")
|
||||||
|
|
||||||
(deflisten bt
|
(deflisten bt
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
(label
|
(label
|
||||||
:visible {net.vpn.up}
|
:visible {net.vpn.up}
|
||||||
:class "net-icon net-active"
|
:class "net-icon net-active"
|
||||||
:tooltip "VPN: ${net.vpn.name}"
|
:tooltip {net.vpn.full ? "VPN: all traffic through ${net.vpn.name}" : "WireGuard: ${net.vpn.name}"}
|
||||||
:text "")
|
:text "")
|
||||||
(label
|
(label
|
||||||
:class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}"
|
:class "net-icon ${net.wifi.connected ? 'net-active' : 'net-dim'}"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Network state for the bar icons and the net panel: wifi, ethernet and USB
|
# Network state for the bar icons and the net panel: wifi, ethernet and USB
|
||||||
# tethering. Refreshes on link/address changes and every 30 s (signal level).
|
# tethering. Refreshes on link/address/rule changes and every 30 s (signal level).
|
||||||
|
|
||||||
wifi_iface() { awk 'NR > 2 { sub(":", "", $1); print $1; exit }' /proc/net/wireless; }
|
wifi_iface() { awk 'NR > 2 { sub(":", "", $1); print $1; exit }' /proc/net/wireless; }
|
||||||
eth_iface() { ip -o link 2>/dev/null | awk '$2 ~ /^en[op]/ { sub(":", "", $2); print $2; exit }'; }
|
eth_iface() { ip -o link 2>/dev/null | awk '$2 ~ /^en[op]/ { sub(":", "", $2); print $2; exit }'; }
|
||||||
@@ -84,7 +84,7 @@ state() {
|
|||||||
wg_ifaces() {
|
wg_ifaces() {
|
||||||
{
|
{
|
||||||
systemctl list-units --all --plain --no-legend 'wireguard-*.service' 2>/dev/null \
|
systemctl list-units --all --plain --no-legend 'wireguard-*.service' 2>/dev/null \
|
||||||
| awk '$1 !~ /-peer-/ { sub(/^wireguard-/, "", $1); sub(/\.service$/, "", $1); print $1 }'
|
| awk '$1 !~ /-peer-|-vpn\.service$/ { sub(/^wireguard-/, "", $1); sub(/\.service$/, "", $1); print $1 }'
|
||||||
ip -d -o link 2>/dev/null | awk '/ wireguard / { sub(":", "", $2); print $2 }'
|
ip -d -o link 2>/dev/null | awk '/ wireguard / { sub(":", "", $2); print $2 }'
|
||||||
} | sort -u
|
} | sort -u
|
||||||
}
|
}
|
||||||
@@ -97,10 +97,12 @@ human_bytes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wg_json() { # prints the "wireguard" array and the "vpn" summary
|
wg_json() { # prints the "wireguard" array and the "vpn" summary
|
||||||
local name up ip rx tx peers endpoint peer_unit peer_script sep="" out="[" vpn_up=false vpn_name=""
|
local name up ip rx tx peers endpoint peer_unit peer_script vpn_able vpn sep="" out="[" vpn_up=false vpn_name="" vpn_full=false
|
||||||
while read -r name; do
|
while read -r name; do
|
||||||
[[ -n $name ]] || continue
|
[[ -n $name ]] || continue
|
||||||
up=false ip="" rx=0 tx=0 endpoint=""
|
up=false ip="" rx=0 tx=0 endpoint="" vpn_able=false vpn=false
|
||||||
|
[[ $(systemctl show -p LoadState --value "wireguard-$name-vpn.service" 2>/dev/null) == loaded ]] && vpn_able=true
|
||||||
|
systemctl is-active --quiet "wireguard-$name-vpn.service" 2>/dev/null && vpn=true
|
||||||
if [[ -d /sys/class/net/$name ]]; then
|
if [[ -d /sys/class/net/$name ]]; then
|
||||||
ip -o link show "$name" 2>/dev/null | grep -q '<[^>]*UP' && up=true
|
ip -o link show "$name" 2>/dev/null | grep -q '<[^>]*UP' && up=true
|
||||||
ip=$(ipv4 "$name")
|
ip=$(ipv4 "$name")
|
||||||
@@ -120,14 +122,15 @@ wg_json() { # prints the "wireguard" array and the "vpn" summary
|
|||||||
fi
|
fi
|
||||||
if [[ $up == true && $vpn_up == false ]]; then vpn_up=true vpn_name=$name; fi
|
if [[ $up == true && $vpn_up == false ]]; then vpn_up=true vpn_name=$name; fi
|
||||||
[[ -z $vpn_name ]] && vpn_name=$name
|
[[ -z $vpn_name ]] && vpn_name=$name
|
||||||
out+="$sep{\"name\":\"$(jstr "$name")\",\"up\":$up,\"ip\":\"$ip\",\"rx\":\"$(human_bytes "$rx")\",\"tx\":\"$(human_bytes "$tx")\",\"peers\":\"$(jstr "$peers")\",\"endpoint\":\"$(jstr "$endpoint")\"}"
|
[[ $vpn == true ]] && vpn_full=true vpn_name=$name
|
||||||
|
out+="$sep{\"name\":\"$(jstr "$name")\",\"up\":$up,\"ip\":\"$ip\",\"rx\":\"$(human_bytes "$rx")\",\"tx\":\"$(human_bytes "$tx")\",\"peers\":\"$(jstr "$peers")\",\"endpoint\":\"$(jstr "$endpoint")\",\"vpn_able\":$vpn_able,\"vpn\":$vpn}"
|
||||||
sep=,
|
sep=,
|
||||||
done < <(wg_ifaces)
|
done < <(wg_ifaces)
|
||||||
printf '"wireguard":%s],"vpn":{"up":%s,"name":"%s"}' "$out" "$vpn_up" "$(jstr "$vpn_name")"
|
printf '"wireguard":%s],"vpn":{"up":%s,"full":%s,"name":"%s"}' "$out" "$vpn_up" "$vpn_full" "$(jstr "$vpn_name")"
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() { emit "$(state)"; }
|
refresh() { emit "$(state)"; }
|
||||||
_link_events() { exec ip monitor link address; }
|
_link_events() { exec ip monitor link address rule; }
|
||||||
|
|
||||||
refresh
|
refresh
|
||||||
mux_init
|
mux_init
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Toggle VPN mode (all traffic through the tunnel) of WireGuard interface $1,
|
||||||
|
# independently of the tunnel itself. Starting it brings the tunnel up.
|
||||||
|
# Needs the polkit rule from modules/nixos/system/network/wireguard.
|
||||||
|
name=$1
|
||||||
|
[[ -n $name ]] || exit 64
|
||||||
|
detach_self "$@"
|
||||||
|
unit=wireguard-$name-vpn.service
|
||||||
|
if systemctl is-active --quiet "$unit"; then
|
||||||
|
systemctl stop "$unit"
|
||||||
|
else
|
||||||
|
systemctl start "$unit"
|
||||||
|
fi
|
||||||
@@ -96,12 +96,19 @@
|
|||||||
(box :orientation "v" :space-evenly false :class "wg-row"
|
(box :orientation "v" :space-evenly false :class "wg-row"
|
||||||
(box :orientation "h" :space-evenly false :valign "center"
|
(box :orientation "h" :space-evenly false :valign "center"
|
||||||
(label :class "wg-name ${wg.up ? 'wg-up' : 'wg-down'}" :halign "start" :hexpand true :text {wg.name})
|
(label :class "wg-name ${wg.up ? 'wg-up' : 'wg-down'}" :halign "start" :hexpand true :text {wg.name})
|
||||||
|
(button
|
||||||
|
:class "net-toggle-btn net-add-btn ${wg.vpn ? 'net-toggle-on' : 'net-toggle-off'}"
|
||||||
|
:visible {wg.vpn_able}
|
||||||
|
:onclick "scripts/net/wg-vpn-toggle ${wg.name}"
|
||||||
|
:tooltip {wg.vpn ? "VPN: all traffic through ${wg.name}" : "VPN off: only the private subnet"}
|
||||||
|
(label :text ""))
|
||||||
(button
|
(button
|
||||||
:class "net-toggle-btn ${wg.up ? 'net-toggle-on' : 'net-toggle-off'}"
|
:class "net-toggle-btn ${wg.up ? 'net-toggle-on' : 'net-toggle-off'}"
|
||||||
:onclick "scripts/net/wg-toggle ${wg.name}"
|
:onclick "scripts/net/wg-toggle ${wg.name}"
|
||||||
:tooltip {wg.up ? "Disconnect" : "Connect"}
|
:tooltip {wg.up ? "Disconnect" : "Connect"}
|
||||||
(label :text {wg.up ? "" : ""})))
|
(label :text {wg.up ? "" : ""})))
|
||||||
(box :orientation "v" :space-evenly false :visible {wg.up}
|
(box :orientation "v" :space-evenly false :visible {wg.up}
|
||||||
|
(netinfo-row :label "Routing" :value {wg.vpn ? "All traffic" : "Private subnet"})
|
||||||
(netinfo-row :label "IP" :value {wg.ip})
|
(netinfo-row :label "IP" :value {wg.ip})
|
||||||
(netinfo-row :label "Peer" :value {wg.endpoint != "" ? "${wg.peers} · ${wg.endpoint}" : wg.peers})
|
(netinfo-row :label "Peer" :value {wg.endpoint != "" ? "${wg.peers} · ${wg.endpoint}" : wg.peers})
|
||||||
(netinfo-row :label "Traffic" :value " ${wg.rx} ${wg.tx}"))
|
(netinfo-row :label "Traffic" :value " ${wg.rx} ${wg.tx}"))
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ let
|
|||||||
"scripts/net/bt" = mkScript "bt" ./bar/scripts/net/bt [ jq glib ];
|
"scripts/net/bt" = mkScript "bt" ./bar/scripts/net/bt [ jq glib ];
|
||||||
"scripts/net/bt-toggle" = mkScript "bt-toggle" ./bar/scripts/net/bt-toggle [ bluez ];
|
"scripts/net/bt-toggle" = mkScript "bt-toggle" ./bar/scripts/net/bt-toggle [ bluez ];
|
||||||
"scripts/net/wg-toggle" = mkScript "wg-toggle" ./bar/scripts/net/wg-toggle [ ];
|
"scripts/net/wg-toggle" = mkScript "wg-toggle" ./bar/scripts/net/wg-toggle [ ];
|
||||||
|
"scripts/net/wg-vpn-toggle" = mkScript "wg-vpn-toggle" ./bar/scripts/net/wg-vpn-toggle [ ];
|
||||||
"scripts/net/wifi-connect" = mkScript "wifi-connect" ./bar/scripts/net/wifi-connect [ eww wpa_supplicant wofi libnotify ];
|
"scripts/net/wifi-connect" = mkScript "wifi-connect" ./bar/scripts/net/wifi-connect [ eww wpa_supplicant wofi libnotify ];
|
||||||
"scripts/sys/gpu" = mkScript "gpu" ./bar/scripts/sys/gpu [ custom.amdgpu_top jq ];
|
"scripts/sys/gpu" = mkScript "gpu" ./bar/scripts/sys/gpu [ custom.amdgpu_top jq ];
|
||||||
"scripts/sys/memory" = mkScript "memory" ./bar/scripts/sys/memory [ ];
|
"scripts/sys/memory" = mkScript "memory" ./bar/scripts/sys/memory [ ];
|
||||||
@@ -52,6 +53,12 @@ in {
|
|||||||
# graphical session, opens the bar once the daemon answers, and is
|
# graphical session, opens the bar once the daemon answers, and is
|
||||||
# restarted on crash. `eww-bar` (packages/eww-bar) does the heavy
|
# restarted on crash. `eww-bar` (packages/eww-bar) does the heavy
|
||||||
# lifting; kanshi calls `eww-bar place` to move the bar between outputs.
|
# lifting; kanshi calls `eww-bar place` to move the bar between outputs.
|
||||||
|
home.activation.ewwReload = lib.hm.dag.entryAfter [ "linkGeneration" ] ''
|
||||||
|
if ${pkgs.systemd}/bin/systemctl --user is-active --quiet eww.service; then
|
||||||
|
run ${ewwBar} reload || true
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
systemd.user.services.eww = {
|
systemd.user.services.eww = {
|
||||||
Unit = {
|
Unit = {
|
||||||
Description = "eww daemon and bar";
|
Description = "eww daemon and bar";
|
||||||
|
|||||||
@@ -5,6 +5,37 @@
|
|||||||
(p.syscfg.net.wg.enable == true) &&
|
(p.syscfg.net.wg.enable == true) &&
|
||||||
(p.syscfg.net.wg.pubkey != config.syscfg.net.wg.pubkey);
|
(p.syscfg.net.wg.pubkey != config.syscfg.net.wg.pubkey);
|
||||||
activePeers = builtins.filter isValidPeer config.syscfg.peers;
|
activePeers = builtins.filter isValidPeer config.syscfg.peers;
|
||||||
|
|
||||||
|
isServer = config.syscfg.server ? wireguard && config.syscfg.server.wireguard;
|
||||||
|
vpnPeer = {
|
||||||
|
name = "vpn-helcel";
|
||||||
|
publicKey = "NFBJvYXZC+bd62jhrKnM7/pugidWhgR6+C5qIiUiq3Q=";
|
||||||
|
allowedIPs = [ "10.10.1.0/24" "fd10:10:10::0/64" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
vpnTable = "51820";
|
||||||
|
vpnDown = pkgs.writeShellScript "wg0-vpn-down" ''
|
||||||
|
PATH=${lib.makeBinPath [ pkgs.iproute2 pkgs.wireguard-tools ]}
|
||||||
|
for f in -4 -6; do
|
||||||
|
ip $f rule del pref 31000 2>/dev/null
|
||||||
|
ip $f rule del pref 31001 2>/dev/null
|
||||||
|
ip $f route flush table ${vpnTable} 2>/dev/null
|
||||||
|
done
|
||||||
|
wg set wg0 fwmark off peer ${vpnPeer.publicKey} allowed-ips ${lib.concatStringsSep "," vpnPeer.allowedIPs} 2>/dev/null
|
||||||
|
true
|
||||||
|
'';
|
||||||
|
vpnUp = pkgs.writeShellScript "wg0-vpn-up" ''
|
||||||
|
set -e
|
||||||
|
PATH=${lib.makeBinPath [ pkgs.iproute2 pkgs.wireguard-tools pkgs.procps ]}
|
||||||
|
${vpnDown}
|
||||||
|
sysctl -q net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
wg set wg0 fwmark ${vpnTable} peer ${vpnPeer.publicKey} allowed-ips 0.0.0.0/0,::/0
|
||||||
|
for f in -4 -6; do
|
||||||
|
ip $f route replace default dev wg0 table ${vpnTable}
|
||||||
|
ip $f rule add table main suppress_prefixlength 0 pref 31000
|
||||||
|
ip $f rule add not fwmark ${vpnTable} table ${vpnTable} pref 31001
|
||||||
|
done
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf (config.syscfg.net.wg.enable) {
|
config = lib.mkIf (config.syscfg.net.wg.enable) {
|
||||||
@@ -18,20 +49,17 @@ in
|
|||||||
listenPort = 1515;
|
listenPort = 1515;
|
||||||
mtu = 1340;
|
mtu = 1340;
|
||||||
peers =
|
peers =
|
||||||
if (config.syscfg.server ? wireguard && config.syscfg.server.wireguard) then
|
if isServer then
|
||||||
map (p: {
|
map (p: {
|
||||||
name = p.syscfg.hostname;
|
name = p.syscfg.hostname;
|
||||||
publicKey = p.syscfg.net.wg.pubkey;
|
publicKey = p.syscfg.net.wg.pubkey;
|
||||||
allowedIPs = [ p.syscfg.net.wg.ip4 p.syscfg.net.wg.ip6 ];
|
allowedIPs = [ p.syscfg.net.wg.ip4 p.syscfg.net.wg.ip6 ];
|
||||||
}) activePeers
|
}) activePeers
|
||||||
else
|
else
|
||||||
[{
|
[(vpnPeer // {
|
||||||
allowedIPs = [ "10.10.1.0/24" "fd10:10:10::0/64" ];
|
|
||||||
name = "vpn-helcel";
|
|
||||||
endpoint = "vpn.helcel.net:1515";
|
endpoint = "vpn.helcel.net:1515";
|
||||||
publicKey = "NFBJvYXZC+bd62jhrKnM7/pugidWhgR6+C5qIiUiq3Q=";
|
|
||||||
persistentKeepalive = 30;
|
persistentKeepalive = 30;
|
||||||
}];
|
})];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -59,7 +87,23 @@ in
|
|||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s"; # Wait 2 seconds before retrying the domain query
|
RestartSec = "10s"; # Wait 2 seconds before retrying the domain query
|
||||||
};
|
};
|
||||||
startLimitIntervalSec = 0;
|
startLimitIntervalSec = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services."wireguard-wg0-vpn" = lib.mkIf (!isServer) {
|
||||||
|
description = "WireGuard wg0 - route all traffic";
|
||||||
|
bindsTo = [ "wireguard-wg0.service" ];
|
||||||
|
wants = [ "wireguard-wg0-peer-vpn-helcel.service" ];
|
||||||
|
partOf = [ "wireguard-wg0-peer-vpn-helcel.service" ];
|
||||||
|
after = [ "wireguard-wg0.service" "wireguard-wg0-peer-vpn-helcel.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = vpnUp;
|
||||||
|
ExecStop = vpnDown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.checkReversePath = lib.mkIf (!isServer) "loose";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user