187 lines
No EOL
4.9 KiB
Bash
187 lines
No EOL
4.9 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# ============================================
|
|
# Lifecycle
|
|
# ============================================
|
|
|
|
function config::on_load() {
|
|
config::_init_defaults
|
|
config::load
|
|
config::validate
|
|
fmt::set_date_format "${_FMT_DATE_FORMAT:-iso}"
|
|
}
|
|
|
|
# ============================================
|
|
# Defaults
|
|
# ============================================
|
|
|
|
function config::_init_defaults() {
|
|
_WG_INTERFACE="${WG_INTERFACE:-wg0}"
|
|
_WG_DNS="${WG_DNS:-10.0.0.103}"
|
|
_WG_LAN="${WG_LAN:-10.0.0.0/24}"
|
|
_WG_SUBNET="${WG_SUBNET:-10.1.0.0/16}"
|
|
_WG_PORT="${WG_PORT:-51820}"
|
|
_WG_ENDPOINT="${WG_ENDPOINT:-}"
|
|
|
|
# Derived
|
|
_WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
|
|
_WG_SERVER_PUBLIC_KEY_FILE="$(ctx::wg)/server_public.key"
|
|
_WG_SERVER_PRIVATE_KEY_FILE="$(ctx::wg)/server_private.key"
|
|
_WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
|
|
_WG_TUNNEL_FULL="0.0.0.0/0, ::/0"
|
|
}
|
|
|
|
# ============================================
|
|
# Load overrides from .wgctl/wgctl.conf
|
|
# ============================================
|
|
|
|
function config::load() {
|
|
local conf_file
|
|
conf_file="$(ctx::data)/wgctl.conf"
|
|
[[ ! -f "$conf_file" ]] && return 0
|
|
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
|
[[ "$key" =~ ^[[:space:]]*# ]] && continue
|
|
[[ -z "${key// }" ]] && continue
|
|
key="${key// /}"
|
|
value="${value// /}"
|
|
case "$key" in
|
|
WG_INTERFACE) _WG_INTERFACE="$value" ;;
|
|
WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
|
|
WG_DNS) _WG_DNS="$value" ;;
|
|
WG_PORT) _WG_PORT="$value" ;;
|
|
WG_SUBNET) _WG_SUBNET="$value" ;;
|
|
WG_LAN) _WG_LAN="$value" ;;
|
|
# Add debug temporarily to config::load:
|
|
DATE_FORMAT)
|
|
log::debug "config: setting date format to $value"
|
|
_FMT_DATE_FORMAT="$value"
|
|
fmt::set_date_format "$value"
|
|
;;
|
|
esac
|
|
done < "$conf_file"
|
|
|
|
# Recompute derived values after overrides
|
|
_WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
|
|
_WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
|
|
}
|
|
|
|
# ============================================
|
|
# Device Type → Subnet Mapping
|
|
# ============================================
|
|
|
|
declare -gA DEVICE_SUBNETS=(
|
|
[desktop]="10.1.1"
|
|
[laptop]="10.1.2"
|
|
[phone]="10.1.3"
|
|
[tablet]="10.1.4"
|
|
[guest]="10.1.100"
|
|
[guest-desktop]="10.1.101"
|
|
[guest-laptop]="10.1.102"
|
|
[guest-phone]="10.1.103"
|
|
[guest-tablet]="10.1.104"
|
|
)
|
|
|
|
# ============================================
|
|
# Tunnel Modes
|
|
# ============================================
|
|
|
|
declare -gA DEVICE_TUNNEL_MODE=(
|
|
[desktop]="split"
|
|
[laptop]="split"
|
|
[phone]="split"
|
|
[tablet]="split"
|
|
[guest]="split"
|
|
[guest-desktop]="split"
|
|
[guest-laptop]="split"
|
|
[guest-phone]="split"
|
|
[guest-tablet]="split"
|
|
)
|
|
|
|
# ============================================
|
|
# Accessors
|
|
# ============================================
|
|
|
|
function config::interface() { echo "$_WG_INTERFACE"; }
|
|
function config::config_file() { echo "$_WG_CONFIG"; }
|
|
function config::endpoint() { echo "$_WG_ENDPOINT"; }
|
|
function config::dns() { echo "$_WG_DNS"; }
|
|
function config::port() { echo "$_WG_PORT"; }
|
|
function config::subnet() { echo "$_WG_SUBNET"; }
|
|
function config::lan() { echo "$_WG_LAN"; }
|
|
function config::tunnel_split() { echo "$_WG_TUNNEL_SPLIT"; }
|
|
function config::tunnel_full() { echo "$_WG_TUNNEL_FULL"; }
|
|
|
|
function config::server_public_key() {
|
|
cat "$_WG_SERVER_PUBLIC_KEY_FILE"
|
|
}
|
|
|
|
function config::device_types() {
|
|
local types
|
|
{ set +u; types="${!DEVICE_SUBNETS[@]}"; set -u; }
|
|
echo "$types"
|
|
}
|
|
|
|
function config::is_valid_type() {
|
|
local type="$1"
|
|
local subnet
|
|
subnet=$(config::subnet_for "$type")
|
|
[[ -n "$subnet" ]]
|
|
}
|
|
|
|
function config::is_guest_type() {
|
|
local type="$1"
|
|
[[ "$type" == "guest" || "$type" == guest-* ]]
|
|
}
|
|
|
|
function config::subnet_for() {
|
|
local type="$1"
|
|
local result
|
|
{ set +u; result="${DEVICE_SUBNETS[$type]:-}"; set -u; }
|
|
echo "$result"
|
|
}
|
|
|
|
function config::default_tunnel_for() {
|
|
local type="$1"
|
|
local result
|
|
{ set +u; result="${DEVICE_TUNNEL_MODE[$type]:-split}"; set -u; }
|
|
echo "$result"
|
|
}
|
|
|
|
function config::allowed_ips_for() {
|
|
local type="$1"
|
|
local tunnel="${2:-}"
|
|
|
|
if [[ -z "$tunnel" ]]; then
|
|
tunnel=$(config::default_tunnel_for "$type")
|
|
fi
|
|
|
|
case "$tunnel" in
|
|
full) echo "$_WG_TUNNEL_FULL" ;;
|
|
split) echo "$_WG_TUNNEL_SPLIT" ;;
|
|
*)
|
|
log::error "Unknown tunnel mode: ${tunnel} (use 'split' or 'full')"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ============================================
|
|
# Validation
|
|
# ============================================
|
|
|
|
function config::validate() {
|
|
if [[ ! -f "$_WG_SERVER_PUBLIC_KEY_FILE" ]]; then
|
|
log::error "Server public key not found: ${_WG_SERVER_PUBLIC_KEY_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$_WG_SERVER_PRIVATE_KEY_FILE" ]]; then
|
|
log::error "Server private key not found: ${_WG_SERVER_PRIVATE_KEY_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$_WG_CONFIG" ]]; then
|
|
log::error "WireGuard config not found: ${_WG_CONFIG}"
|
|
exit 1
|
|
fi
|
|
} |