Utoljára aktív 1 month ago

Revízió d2d939bc3ecde2ca356bf456cbfeca8e42fa92f2

gistfile1.txt Eredeti
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
27function config::_init_defaults() {
28 _WG_INTERFACE="${WG_INTERFACE:-wg0}"
29 _WG_DNS="${WG_DNS:-10.0.0.103}"
30 _WG_LAN="${WG_LAN:-10.0.0.0/24}"
31 _WG_SUBNET="${WG_SUBNET:-10.1.0.0/16}"
32 _WG_PORT="${WG_PORT:-51820}"
33 _WG_ENDPOINT="${WG_ENDPOINT:-}"
34 _WG_HANDSHAKE_CHECK_TIME_SEC="${WG_HANDSHAKE_CHECK_TIME_SEC:-180}"
35
36 # Derived
37 _WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
38 _WG_SERVER_PUBLIC_KEY_FILE="$(ctx::wg)/server_public.key"
39 _WG_SERVER_PRIVATE_KEY_FILE="$(ctx::wg)/server_private.key"
40 _WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
41 _WG_TUNNEL_FULL="0.0.0.0/0, ::/0"
42}
43
44# ============================================
45# Validation
46# ============================================
47
48function config::validate() {
49 local errors=()
50
51 # Required fields
52 local endpoint
53 endpoint=$(config::endpoint)
54 if [[ -z "$endpoint" ]]; then
55 errors+=("WG_ENDPOINT is not set — required for client config generation")
56 elif [[ "$endpoint" != *:* ]]; then
57 errors+=("WG_ENDPOINT must include port (e.g. wg.example.com:51820)")
58 fi
59
60 local port
61 port=$(config::port)
62 if [[ -z "$port" ]]; then
63 errors+=("WG_LISTEN_PORT is not set")
64 elif ! [[ "$port" =~ ^[0-9]+$ ]] || (( port < 1 || port > 65535 )); then
65 errors+=("WG_LISTEN_PORT must be a valid port number (1-65535)")
66 fi
67
68 local dns
69 dns=$(config::dns)
70 if [[ -z "$dns" ]]; then
71 errors+=("WG_DNS is not set — required for client configs")
72 elif ! ip::is_valid "$dns"; then
73 errors+=("WG_DNS must be a valid IP address")
74 fi
75
76 local subnet
77 subnet=$(config::subnet)
78 if [[ -z "$subnet" ]]; then
79 errors+=("WG_SUBNET is not set — required for IP allocation")
80 fi
81
82 local interface
83 interface=$(config::interface)
84 if [[ -z "$interface" ]]; then
85 errors+=("WG_INTERFACE is not set, defaulting to wg0")
86 fi
87
88 # Warn-only fields
89 local lan
90 lan=$(config::lan)
91 if [[ -z "$lan" ]]; then
92 log::wg_warning "WG_LAN is not set — some rule features may not work correctly"
93 fi
94
95 if [[ ${#errors[@]} -gt 0 ]]; then
96 log::error "wgctl configuration errors:"
97 for err in "${errors[@]}"; do
98 printf " ✗ %s\n" "$err" >&2
99 done
100 printf "\n Edit /etc/wireguard/.wgctl/wgctl.conf to fix these issues.\n\n" >&2
101 return 1
102 fi
103
104 return 0
105}
106
107# ============================================
108# Load overrides from .wgctl/wgctl.conf
109# ============================================
110
111function config::load() {
112 local conf_file
113 conf_file="$(ctx::data)/wgctl.conf"
114 [[ ! -f "$conf_file" ]] && return 0
115 while IFS='=' read -r key value || [[ -n "$key" ]]; do
116 [[ "$key" =~ ^[[:space:]]*# ]] && continue
117 [[ -z "${key// }" ]] && continue
118 key="${key// /}"
119 value="${value// /}"
120 case "$key" in
121 WG_INTERFACE) _WG_INTERFACE="$value" ;;
122 WG_ENDPOINT) _WG_ENDPOINT="$value" ;;
123 WG_DNS) _WG_DNS="$value" ;;
124 WG_PORT) _WG_PORT="$value" ;;
125 WG_SUBNET) _WG_SUBNET="$value" ;;
126 WG_LAN) _WG_LAN="$value" ;;
127 WG_HANDSHAKE_CHECK_TIME_SEC) _WG_HANDSHAKE_CHECK_TIME_SEC="$value" ;;
128 ACTIVITY_LOW_BYTES) _ACTIVITY_LOW_BYTES="$value" ;;
129 ACTIVITY_MED_BYTES) _ACTIVITY_MED_BYTES="$value" ;;
130 ACTIVITY_HIGH_BYTES) _ACTIVITY_HIGH_BYTES="$value" ;;
131 DATE_FORMAT)
132 _FMT_DATE_FORMAT="$value"
133 fmt::set_date_format "$value"
134 ;;
135 esac
136 done < "$conf_file"
137
138 # Recompute derived values after overrides
139 _WG_CONFIG="$(ctx::wg)/${_WG_INTERFACE}.conf"
140 _WG_TUNNEL_SPLIT="${_WG_SUBNET}, ${_WG_LAN}"
141}
142
143# ============================================
144# Device Type → Subnet Mapping
145# ============================================
146
147declare -gA DEVICE_SUBNETS=(
148 [desktop]="10.1.1"
149 [laptop]="10.1.2"
150 [phone]="10.1.3"
151 [tablet]="10.1.4"
152 [guest]="10.1.100"
153 [guest-desktop]="10.1.101"
154 [guest-laptop]="10.1.102"
155 [guest-phone]="10.1.103"
156 [guest-tablet]="10.1.104"
157)
158
159# ============================================
160# Tunnel Modes
161# ============================================
162
163declare -gA DEVICE_TUNNEL_MODE=(
164 [desktop]="split"
165 [laptop]="split"
166 [phone]="split"
167 [tablet]="split"
168 [guest]="split"
169 [guest-desktop]="split"
170 [guest-laptop]="split"
171 [guest-phone]="split"
172 [guest-tablet]="split"
173)
174
175# ============================================
176# Accessors
177# ============================================
178
179function config::interface() { echo "$_WG_INTERFACE"; }
180function config::config_file() { echo "$_WG_CONFIG"; }
181function config::endpoint() { echo "$_WG_ENDPOINT"; }
182function config::dns() { echo "$_WG_DNS"; }
183function config::port() { echo "$_WG_PORT"; }
184function config::subnet() { echo "$_WG_SUBNET"; }
185function config::lan() { echo "$_WG_LAN"; }
186function config::tunnel_split() { echo "$_WG_TUNNEL_SPLIT"; }
187function config::tunnel_full() { echo "$_WG_TUNNEL_FULL"; }
188function config::handshake_time_sec() { echo "$_WG_HANDSHAKE_CHECK_TIME_SEC"; }
189function config::activity_total_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
190function config::activity_total_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
191function config::activity_total_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
192function config::activity_current_low() { echo "$_ACTIVITY_TOTAL_LOW_BYTES"; }
193function config::activity_current_med() { echo "$_ACTIVITY_TOTAL_MED_BYTES"; }
194function config::activity_current_high() { echo "$_ACTIVITY_TOTAL_HIGH_BYTES"; }
195function config::server_public_key() { cat "$_WG_SERVER_PUBLIC_KEY_FILE"; }
196
197function config::device_types() {
198 local types
199 { set +u; types="${!DEVICE_SUBNETS[@]}"; set -u; }
200 echo "$types"
201}
202
203function config::is_valid_type() {
204 local type="$1"
205 local subnet
206 subnet=$(config::subnet_for "$type")
207 [[ -n "$subnet" ]]
208}
209
210function config::is_guest_type() {
211 local type="$1"
212 [[ "$type" == "guest" || "$type" == guest-* ]]
213}
214
215function config::subnet_for() {
216 local type="$1"
217 local result
218 { set +u; result="${DEVICE_SUBNETS[$type]:-}"; set -u; }
219 echo "$result"
220}
221
222function config::default_tunnel_for() {
223 local type="$1"
224 local result
225 { set +u; result="${DEVICE_TUNNEL_MODE[$type]:-split}"; set -u; }
226 echo "$result"
227}
228
229function config::allowed_ips_for() {
230 local type="$1"
231 local tunnel="${2:-}"
232
233 if [[ -z "$tunnel" ]]; then
234 tunnel=$(config::default_tunnel_for "$type")
235 fi
236
237 case "$tunnel" in
238 full) echo "$_WG_TUNNEL_FULL" ;;
239 split) echo "$_WG_TUNNEL_SPLIT" ;;
240 *)
241 log::error "Unknown tunnel mode: ${tunnel} (use 'split' or 'full')"
242 return 1
243 ;;
244 esac
245}
246
247# ============================================
248# Validation
249# ============================================
250
251function config::validate() {
252 if [[ ! -f "$_WG_SERVER_PUBLIC_KEY_FILE" ]]; then
253 log::error "Server public key not found: ${_WG_SERVER_PUBLIC_KEY_FILE}"
254 exit 1
255 fi
256
257 if [[ ! -f "$_WG_SERVER_PRIVATE_KEY_FILE" ]]; then
258 log::error "Server private key not found: ${_WG_SERVER_PRIVATE_KEY_FILE}"
259 exit 1
260 fi
261
262 if [[ ! -f "$_WG_CONFIG" ]]; then
263 log::error "WireGuard config not found: ${_WG_CONFIG}"
264 exit 1
265 fi
266}
267