Ostatnio aktywny 1 month ago

Rewizja e5c8f36889c48ee2730288224fd4dd50b9a6f510

config.module.sh Surowy
1#!/usr/bin/env bash
2
3# ============================================
4# Lifecycle
5# ============================================
6
7function config::on_load() {
8 config::_init_defaults
9 config::load
10 config::validate
11 fmt::set_date_format "${_FMT_DATE_FORMAT:-iso}"
12}
13
14# ============================================
15# Defaults
16# ============================================
17
18# Activity thresholds
19declare -g _ACTIVITY_TOTAL_LOW_BYTES="${ACTIVITY_TOTAL_LOW_BYTES:-1000000}"
20declare -g _ACTIVITY_TOTAL_MED_BYTES="${ACTIVITY_TOTAL_MED_BYTES:-10000000}"
21declare -g _ACTIVITY_TOTAL_HIGH_BYTES="${ACTIVITY_TOTAL_HIGH_BYTES:-100000000}"
22
23declare -g _ACTIVITY_CURRENT_LOW_BYTES="${ACTIVITY_CURRENT_LOW_BYTES:-1000000}"
24declare -g _ACTIVITY_CURRENT_MED_BYTES="${ACTIVITY_CURRENT_MED_BYTES:-10000000}"
25declare -g _ACTIVITY_CURRENT_HIGH_BYTES="${ACTIVITY_CURRENT_HIGH_BYTES:-100000000}"
26
27
28function config::_init_defaults() {
29 _WG_INTERFACE="${WG_INTERFACE:-wg0}"
30 _WG_DNS="${WG_DNS:-10.0.0.103}"
31 _WG_DNS_FALLBACK="${WG_DNS_FALLBACK:-}"
32 _WG_LAN="${WG_LAN:-10.0.0.0/24}"
33 _WG_SUBNET="${WG_SUBNET:-10.1.0.0/16}"
34 _WG_PORT="${WG_PORT:-51820}"
35 _WG_ENDPOINT="${WG_ENDPOINT:-}"
36 _WG_HANDSHAKE_CHECK_TIME_SEC="${WG_HANDSHAKE_CHECK_TIME_SEC:-180}"
37
38 # Derived
39 _WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
40 _WG_SERVER_PUBLIC_KEY_FILE="$(ctx::wg)/server_public.key"
41 _WG_SERVER_PRIVATE_KEY_FILE="$(ctx::wg)/server_private.key"
42 _WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
43 _WG_TUNNEL_FULL="0.0.0.0/0, ::/0"
44}
45
46# ============================================
47# Validation
48# ============================================
49
50function config::validate() {
51 local errors=()
52
53 # Server key and config files
54 if [[ ! -f "$_WG_SERVER_PUBLIC_KEY_FILE" ]]; then
55 errors+=("Server public key not found: ${_WG_SERVER_PUBLIC_KEY_FILE}")
56 fi
57 if [[ ! -f "$_WG_SERVER_PRIVATE_KEY_FILE" ]]; then
58 errors+=("Server private key not found: ${_WG_SERVER_PRIVATE_KEY_FILE}")
59 fi
60 if [[ ! -f "$_WG_CONFIG" ]]; then
61 errors+=("WireGuard config not found: ${_WG_CONFIG}")
62 fi
63
64 # Required config values
65 local endpoint
66 endpoint=$(config::endpoint)
67 if [[ -z "$endpoint" ]]; then
68 errors+=("WG_ENDPOINT is not set — required for client config generation")
69 elif [[ "$endpoint" != *:* ]]; then
70 errors+=("WG_ENDPOINT must include port (e.g. wg.example.com:51820)")
71 fi
72
73 local port
74 port=$(config::port)
75 if [[ -z "$port" ]]; then
76 errors+=("WG_PORT is not set")
77 elif ! [[ "$port" =~ ^[0-9]+$ ]] || (( port < 1 || port > 65535 )); then
78 errors+=("WG_PORT must be a valid port number (1-65535)")
79 fi
80
81 local dns
82 dns=$(config::dns)
83 if [[ -z "$dns" ]]; then
84 errors+=("WG_DNS is not set — required for client configs")
85 elif ! ip::is_valid "$dns"; then
86 errors+=("WG_DNS must be a valid IP address")
87 fi
88
89 local subnet
90 subnet=$(config::subnet)
91 if [[ -z "$subnet" ]]; then
92 errors+=("WG_SUBNET is not set — required for IP allocation")
93 fi
94
95 # Warn-only
96 local lan
97 lan=$(config::lan)
98 if [[ -z "$lan" ]]; then
99 log::wg_warning "WG_LAN is not set — some rule features may not work correctly"
100 fi
101
102 if [[ ${#errors[@]} -gt 0 ]]; then
103 log::error "wgctl configuration errors:"
104 for err in "${errors[@]}"; do
105 printf " ✗ %s\n" "$err" >&2
106 done
107 printf "\n Edit /etc/wireguard/.wgctl/wgctl.conf to fix these issues.\n\n" >&2
108 return 1
109 fi
110
111 return 0
112}
113
114# ============================================
115# Load overrides from .wgctl/wgctl.conf
116# ============================================
117
118function config::load() {
119 local conf_file
120 conf_file="$(ctx::data)/wgctl.conf"
121 [[ ! -f "$conf_file" ]] && return 0
122 while IFS='=' read -r key value || [[ -n "$key" ]]; do
123 [[ "$key" =~ ^[[:space:]]*# ]] && continue
124 [[ -z "${key// }" ]] && continue
125 key="${key// /}"
126 value="${value// /}"
127 case "$key" in
128 WG_INTERFACE) _WG_INTERFACE="$value" ;;
129 WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
130 WG_DNS) _WG_DNS="$value" ;;
131 WG_DNS_FALLBACK) _WG_DNS_FALLBACK="$value" ;;
132 WG_PORT) _WG_PORT="$value" ;;
133 WG_SUBNET) _WG_SUBNET="$value" ;;
134 WG_LAN) _WG_LAN="$value" ;;
135 WG_HANDSHAKE_CHECK_TIME_SEC) _WG_HANDSHAKE_CHECK_TIME_SEC="$value" ;;
136 ACTIVITY_LOW_BYTES) _ACTIVITY_LOW_BYTES="$value" ;;
137 ACTIVITY_MED_BYTES) _ACTIVITY_MED_BYTES="$value" ;;
138 ACTIVITY_HIGH_BYTES) _ACTIVITY_HIGH_BYTES="$value" ;;
139 DATE_FORMAT)
140 _FMT_DATE_FORMAT="$value"
141 fmt::set_date_format "$value"
142 ;;
143 esac
144 done < "$conf_file"
145
146 # Recompute derived values after overrides
147 _WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
148 _WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
149}
150
151# ============================================
152# Accessors
153# ============================================
154
155function config::interface() { echo "$_WG_INTERFACE"; }
156function config::config_file() { echo "$_WG_CONFIG"; }
157function config::endpoint() { echo "$_WG_ENDPOINT"; }
158function config::dns() { echo "$_WG_DNS"; }
159function config::dns_fallback() { echo "${_WG_DNS_FALLBACK:-}"; }
160function config::port() { echo "$_WG_PORT"; }
161function config::subnet() { echo "$_WG_SUBNET"; }
162function config::lan() { echo "$_WG_LAN"; }
163function config::tunnel_split() { echo "$_WG_TUNNEL_SPLIT"; }
164function config::tunnel_full() { echo "$_WG_TUNNEL_FULL"; }
165function config::handshake_time_sec() { echo "$_WG_HANDSHAKE_CHECK_TIME_SEC"; }
166function config::activity_total_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
167function config::activity_total_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
168function config::activity_total_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
169function config::activity_current_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
170function config::activity_current_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
171function config::activity_current_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
172function config::server_public_key() { cat "$_WG_SERVER_PUBLIC_KEY_FILE"; }
173
174function config::allowed_ips_for() {
175 local tunnel="${1:-split}"
176 case "$tunnel" in
177 full) echo "$_WG_TUNNEL_FULL" ;;
178 split) echo "$_WG_TUNNEL_SPLIT" ;;
179 *)
180 log::error "Unknown tunnel mode: ${tunnel} (use 'split' or 'full')"
181 return 1
182 ;;
183 esac
184}
185
186function config::dns_string() {
187 local fallback
188 fallback=$(config::dns_fallback)
189 if [[ -n "$fallback" ]]; then
190 echo "$(config::dns), ${fallback}"
191 else
192 echo "$(config::dns)"
193 fi
194}
195