sane-vpn: add a way to route traffic specifically through unmetered connections
This commit is contained in:
@@ -210,7 +210,7 @@ let
|
|||||||
vpn = static-nix-shell.mkBash {
|
vpn = static-nix-shell.mkBash {
|
||||||
pname = "sane-vpn";
|
pname = "sane-vpn";
|
||||||
srcRoot = ./src;
|
srcRoot = ./src;
|
||||||
pkgs = [ "coreutils-full" "iproute2" "jq" "sane-scripts.ip-check" "systemd" ];
|
pkgs = [ "coreutils-full" "iproute2" "jq" "networkmanager-split.nmcli" "sane-scripts.ip-check" "systemd" ];
|
||||||
};
|
};
|
||||||
which = static-nix-shell.mkBash {
|
which = static-nix-shell.mkBash {
|
||||||
pname = "sane-which";
|
pname = "sane-which";
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash -p bash -p coreutils-full -p iproute2 -p jq -p sane-scripts.ip-check -p systemd
|
#!nix-shell -i bash -p bash -p coreutils-full -p iproute2 -p jq -p networkmanager-split.nmcli -p sane-scripts.ip-check -p systemd
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -22,6 +22,10 @@ usageDescription() {
|
|||||||
echo "sane-vpn do -- [COMMAND ...]"
|
echo "sane-vpn do -- [COMMAND ...]"
|
||||||
echo "sane-vpn help"
|
echo "sane-vpn help"
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "special regions:"
|
||||||
|
echo "- none: allow ALL network devices; don't actually re-route traffic through a VPN. useful to make only DNS changes"
|
||||||
|
echo "- unmetered: route traffic PLAINTEXT through whichever unmetered connections (i.e. eth/wifi) are up"
|
||||||
|
echo ""
|
||||||
echo "idioms:"
|
echo "idioms:"
|
||||||
echo "- sane-vpn do none [COMMAND ...]"
|
echo "- sane-vpn do none [COMMAND ...]"
|
||||||
echo " - run the command with a stub resolver instead of my recursive resolver, but no VPN."
|
echo " - run the command with a stub resolver instead of my recursive resolver, but no VPN."
|
||||||
@@ -29,6 +33,8 @@ usageDescription() {
|
|||||||
echo " - patch the entire system to use a stub resolver, but no VPN."
|
echo " - patch the entire system to use a stub resolver, but no VPN."
|
||||||
echo "- sane-vpn --no-proxy-dns up -- [COMMAND ...]"
|
echo "- sane-vpn --no-proxy-dns up -- [COMMAND ...]"
|
||||||
echo " - patch the system to route all traffic over the VPN, but use our stub resolver (still through the VPN) instead of delegating to the VPN owner's resolver"
|
echo " - patch the system to route all traffic over the VPN, but use our stub resolver (still through the VPN) instead of delegating to the VPN owner's resolver"
|
||||||
|
echo "- sane-vpn do unmetered [COMMAND ...]"
|
||||||
|
echo " - run the command using only those interfaces which are unmetered (i.e. ethernet/wifi)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -63,10 +69,43 @@ getVpns() {
|
|||||||
|
|
||||||
# load a specific VPN profile, `"$1"`
|
# load a specific VPN profile, `"$1"`
|
||||||
sourceVpn() {
|
sourceVpn() {
|
||||||
# populates: variables declared above
|
local region="$1"
|
||||||
|
# populates (a subset of) variables declared above
|
||||||
|
case "$region" in
|
||||||
|
(none)
|
||||||
|
name=$(ip -j route get 255 | jq --raw-output '.[0]["dev"]')
|
||||||
|
dns=(1.1.1.1 8.8.8.8)
|
||||||
|
;;
|
||||||
|
(unmetered)
|
||||||
|
# connect only to "unmetered" networks, i.e. ethernet/wifi -- NOT mobile
|
||||||
|
all_networks=$(nmcli --get-values DEVICE,TYPE,STATE device | tr " " "-")
|
||||||
|
ok_networks=()
|
||||||
|
# format is like "wlan0:wifi:connected" or "eth0:ethernet:disconnected"
|
||||||
|
for n in $all_networks; do
|
||||||
|
device=$(echo $n | cut -d ":" -f 1)
|
||||||
|
type=$(echo $n | cut -d ":" -f 2)
|
||||||
|
state=$(echo $n | cut -d ":" -f 3)
|
||||||
|
debug "considering $device ($type, $state)"
|
||||||
|
case "$type-$state" in
|
||||||
|
(ethernet-connected)
|
||||||
|
# ethernet gets high precedence
|
||||||
|
ok_networks=("$device" "${ok_networks[@]}")
|
||||||
|
;;
|
||||||
|
(wifi-connected)
|
||||||
|
# wifi gets low precedence
|
||||||
|
ok_networks+=("$device")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
debug "choosing from networks: ${ok_networks[@]}"
|
||||||
|
name="${ok_networks[0]}"
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
debug "sourcing: ~/.config/sane-vpn/vpns/$1"
|
debug "sourcing: ~/.config/sane-vpn/vpns/$1"
|
||||||
# TODO: don't blindly source this, but parse explicitly as `K=V`
|
# TODO: don't blindly source this, but parse explicitly as `K=V`
|
||||||
source ~/.config/sane-vpn/vpns/$1
|
source ~/.config/sane-vpn/vpns/$1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
canonicalizeRegion() {
|
canonicalizeRegion() {
|
||||||
@@ -106,7 +145,7 @@ vpnToggle() {
|
|||||||
echo before: $(sane-ip-check --no-upnp --retry-duration 2)
|
echo before: $(sane-ip-check --no-upnp --retry-duration 2)
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ "$region" != none ]; then
|
if [ -n "$priorityMain" ] && [ -n "$priorityFwMark" ]; then
|
||||||
# first, allow all non-default routes (prefix-length != 0) a chance to route the packet.
|
# first, allow all non-default routes (prefix-length != 0) a chance to route the packet.
|
||||||
# - this allows the wireguard tunnel itself to pass traffic via our LAN gateway.
|
# - this allows the wireguard tunnel itself to pass traffic via our LAN gateway.
|
||||||
# - incidentally, it allows traffic to LAN devices and other machine-local or virtual networks.
|
# - incidentally, it allows traffic to LAN devices and other machine-local or virtual networks.
|
||||||
@@ -199,12 +238,7 @@ parseCli() {
|
|||||||
getVpns
|
getVpns
|
||||||
canonicalizeRegion
|
canonicalizeRegion
|
||||||
fixupCommand "$@"
|
fixupCommand "$@"
|
||||||
if [ "$region" == none ]; then
|
|
||||||
name=$(ip -j route get 255 | jq --raw-output '.[0]["dev"]')
|
|
||||||
dns=(1.1.1.1 8.8.8.8)
|
|
||||||
else
|
|
||||||
sourceVpn "$region"
|
sourceVpn "$region"
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$noProxyDns" ]; then
|
if [ -n "$noProxyDns" ]; then
|
||||||
dns=()
|
dns=()
|
||||||
|
Reference in New Issue
Block a user