- rule assign: block if rule already in peer's identity - identity rule assign: --migrate flag to remove conflicting direct peer rules - commands/peer.command.sh: update-dns and update-tunnel subcommands - config.sh: config::dns_fallback, config::dns_string - peers.module.sh: peers::get_display_subnet extraction - wgctl peer update-dns --all: retrofits existing peer configs with fallback DNS - wgctl.conf: WG_DNS_FALLBACK support
197 lines
No EOL
5.7 KiB
Bash
197 lines
No EOL
5.7 KiB
Bash
#!/usr/bin/env bash
|
|
# peer.command.sh — peer management operations
|
|
|
|
# ============================================
|
|
# Lifecycle
|
|
# ============================================
|
|
|
|
function cmd::peer::on_load() {
|
|
flag::register --name
|
|
flag::register --type
|
|
flag::register --all
|
|
flag::register --mode
|
|
flag::register --dns
|
|
flag::register --fallback-dns
|
|
flag::register --force
|
|
}
|
|
|
|
# ============================================
|
|
# Help
|
|
# ============================================
|
|
|
|
function cmd::peer::help() {
|
|
cat <<EOF
|
|
Usage: wgctl peer <subcommand> [options]
|
|
|
|
Manage peer configuration and settings.
|
|
|
|
Subcommands:
|
|
update-dns Update DNS settings in client config(s)
|
|
update-tunnel Update tunnel mode (split/full) in client config(s)
|
|
|
|
Options for update-dns:
|
|
--name <name> Target peer
|
|
--all Apply to all peers
|
|
--type <type> Filter by device type
|
|
--dns <ip> Primary DNS (default: from config)
|
|
--fallback-dns <ips> Fallback DNS servers (comma-separated)
|
|
Default: from WG_DNS_FALLBACK in wgctl.conf
|
|
|
|
Options for update-tunnel:
|
|
--name <name> Target peer
|
|
--all Apply to all peers
|
|
--type <type> Filter by device type
|
|
--mode <mode> Tunnel mode: split | full
|
|
--force Skip confirmation for --all
|
|
|
|
Examples:
|
|
wgctl peer update-dns --all
|
|
wgctl peer update-dns --name phone-nuno
|
|
wgctl peer update-dns --name phone-nuno --fallback-dns 9.9.9.9,1.1.1.1
|
|
wgctl peer update-tunnel --all --mode split
|
|
wgctl peer update-tunnel --name phone-nuno --mode full
|
|
EOF
|
|
}
|
|
|
|
# ============================================
|
|
# Run
|
|
# ============================================
|
|
|
|
function cmd::peer::run() {
|
|
local subcmd="${1:-help}"
|
|
shift || true
|
|
case "$subcmd" in
|
|
update-dns) cmd::peer::update_dns "$@" ;;
|
|
update-tunnel) cmd::peer::update_tunnel "$@" ;;
|
|
help) cmd::peer::help ;;
|
|
*)
|
|
log::error "Unknown subcommand: '${subcmd}'"
|
|
cmd::peer::help
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ============================================
|
|
# Update DNS
|
|
# ============================================
|
|
|
|
function cmd::peer::update_dns() {
|
|
local name="" type="" all=false
|
|
local dns="" fallback_dns=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; shift 2 ;;
|
|
--type) type="$2"; shift 2 ;;
|
|
--all) all=true; shift ;;
|
|
--dns) dns="$2"; shift 2 ;;
|
|
--fallback-dns) fallback_dns="$2"; shift 2 ;;
|
|
--help) cmd::peer::help; return ;;
|
|
*) log::error "Unknown flag: $1"; return 1 ;;
|
|
esac
|
|
done
|
|
|
|
[[ -z "$name" && "$all" == "false" ]] && \
|
|
log::error "Specify --name or --all" && return 1
|
|
|
|
# Resolve DNS string
|
|
local primary="${dns:-$(config::dns)}"
|
|
local fallback="${fallback_dns:-$(config::dns_fallback)}"
|
|
local dns_string
|
|
if [[ -n "$fallback" ]]; then
|
|
dns_string="${primary}, ${fallback}"
|
|
else
|
|
dns_string="$primary"
|
|
fi
|
|
|
|
# Collect target peers
|
|
local peers=()
|
|
if $all; then
|
|
while IFS= read -r conf; do
|
|
peers+=("$(basename "$conf" .conf)")
|
|
done < <(find "$(ctx::clients)" -name "*.conf" 2>/dev/null)
|
|
else
|
|
name=$(peers::resolve_and_require "$name" "$type") || return 1
|
|
peers=("$name")
|
|
fi
|
|
|
|
local updated=0
|
|
for peer_name in "${peers[@]}"; do
|
|
local conf
|
|
conf="$(ctx::clients)/${peer_name}.conf"
|
|
[[ ! -f "$conf" ]] && continue
|
|
|
|
# Replace DNS line in-place
|
|
if grep -q "^DNS" "$conf"; then
|
|
sed -i "s|^DNS = .*|DNS = ${dns_string}|" "$conf"
|
|
else
|
|
# Add DNS line after Address line
|
|
sed -i "/^Address/a DNS = ${dns_string}" "$conf"
|
|
fi
|
|
(( updated++ )) || true
|
|
log::debug "Updated DNS for: ${peer_name}"
|
|
done
|
|
|
|
log::wg_success "Updated DNS to '${dns_string}' for ${updated} peer(s)"
|
|
}
|
|
|
|
# ============================================
|
|
# Update Tunnel
|
|
# ============================================
|
|
|
|
function cmd::peer::update_tunnel() {
|
|
local name="" type="" all=false mode="" force=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; shift 2 ;;
|
|
--type) type="$2"; shift 2 ;;
|
|
--all) all=true; shift ;;
|
|
--mode) mode="$2"; shift 2 ;;
|
|
--force) force=true; shift ;;
|
|
--help) cmd::peer::help; return ;;
|
|
*) log::error "Unknown flag: $1"; return 1 ;;
|
|
esac
|
|
done
|
|
|
|
[[ -z "$name" && "$all" == "false" ]] && \
|
|
log::error "Specify --name or --all" && return 1
|
|
[[ -z "$mode" ]] && \
|
|
log::error "Missing required flag: --mode (split|full)" && return 1
|
|
[[ "$mode" != "split" && "$mode" != "full" ]] && \
|
|
log::error "Invalid mode: ${mode} (must be split or full)" && return 1
|
|
|
|
local allowed_ips
|
|
allowed_ips=$(config::allowed_ips_for "$mode")
|
|
|
|
# Collect target peers
|
|
local peers=()
|
|
if $all; then
|
|
if ! $force; then
|
|
read -r -p "Update tunnel mode to '${mode}' for ALL peers? [y/N] " confirm
|
|
case "$confirm" in [yY]*) ;; *) log::info "Aborted"; return 0 ;; esac
|
|
fi
|
|
while IFS= read -r conf; do
|
|
peers+=("$(basename "$conf" .conf)")
|
|
done < <(find "$(ctx::clients)" -name "*.conf" 2>/dev/null)
|
|
else
|
|
name=$(peers::resolve_and_require "$name" "$type") || return 1
|
|
peers=("$name")
|
|
fi
|
|
|
|
local updated=0
|
|
for peer_name in "${peers[@]}"; do
|
|
local conf
|
|
conf="$(ctx::clients)/${peer_name}.conf"
|
|
[[ ! -f "$conf" ]] && continue
|
|
|
|
# Replace AllowedIPs line in-place
|
|
sed -i "s|^AllowedIPs = .*|AllowedIPs = ${allowed_ips}|" "$conf"
|
|
(( updated++ )) || true
|
|
log::debug "Updated tunnel for: ${peer_name}"
|
|
done
|
|
|
|
log::wg_success "Updated tunnel to '${mode}' (${allowed_ips}) for ${updated} peer(s)"
|
|
log::wg "Peers must reconnect to apply the new tunnel mode"
|
|
} |