Son aktivite 2 months ago

nuno bu gisti düzenledi 2 months ago. Düzenlemeye git

1 file changed, 250 insertions

gistfile1.txt(dosya oluşturuldu)

@@ -0,0 +1,250 @@
1 + #!/usr/bin/env bash
2 +
3 + # ============================================
4 + # Lifecycle
5 + # ============================================
6 +
7 + function cmd::add::on_load() {
8 + flag::register --name
9 + flag::register --type
10 + flag::register --subtype
11 + flag::register --rule
12 + flag::register --ip
13 + flag::register --preset
14 + flag::register --guest
15 + flag::register --tunnel
16 + flag::register --show-config
17 + flag::register --show-qr
18 + }
19 +
20 + # ============================================
21 + # Help
22 + # ============================================
23 +
24 + function cmd::add::help() {
25 + cat <<EOF
26 + Usage: wgctl add --name <name> --type <type> [options]
27 +
28 + Add a new WireGuard client.
29 +
30 + Options:
31 + --name <name> Client name (e.g. nuno)
32 + --type <type> Device type: desktop, laptop, phone, tablet, guest
33 + --ip <ip> Override auto-assigned IP (optional)
34 + --preset <name> Apply a firewall preset (repeatable)
35 + --guest Shorthand for --type guest
36 + --tunnel <mode> Tunnel mode: split (default) or full
37 + --show-config Shows the WireGuard peer config
38 + --show-qr Shows the WireGuard config in a QR Code
39 +
40 + Device Types and Subnets:
41 + desktop 10.1.1.x
42 + laptop 10.1.2.x
43 + phone 10.1.3.x
44 + tablet 10.1.4.x
45 + guest 10.1.100.x
46 +
47 + Tunnel Modes:
48 + split Route only VPN subnet + LAN through WireGuard (default)
49 + full Route all traffic through WireGuard
50 +
51 + Examples:
52 + wgctl add --name nuno --type phone
53 + wgctl add --name nuno --type laptop --ip 10.1.2.5
54 + wgctl add --name nuno --type phone --tunnel full
55 + wgctl add --name guest1 --type phone --guest
56 + wgctl add --name restricted --type desktop --preset no-docker --preset no-proxmox
57 + EOF
58 + }
59 +
60 + # ============================================
61 + # Validation
62 + # ============================================
63 +
64 + function cmd::add::validate() {
65 + local name="$1"
66 + local type="$2"
67 + local ip="$3"
68 + local tunnel="$4"
69 +
70 + if [[ -z "$name" ]]; then
71 + log::error "Missing required flag: --name"
72 + return 1
73 + fi
74 +
75 + if [[ -z "$type" ]]; then
76 + log::error "Missing required flag: --type"
77 + return 1
78 + fi
79 +
80 + if ! config::is_valid_type "$type"; then
81 + log::error "Invalid device type: ${type}"
82 + log::info "Valid types: $(config::device_types | tr ' ' ', ')"
83 + return 1
84 + fi
85 +
86 + if [[ -n "$tunnel" && "$tunnel" != "split" && "$tunnel" != "full" ]]; then
87 + log::error "Invalid tunnel mode: ${tunnel} (use 'split' or 'full')"
88 + return 1
89 + fi
90 +
91 + if [[ -n "$ip" ]]; then
92 + ip::require_valid "$ip"
93 + fi
94 +
95 + local full_name="${type}-${name}"
96 +
97 + if [[ -f "$(ctx::clients)/${full_name}.conf" ]]; then
98 + log::error "Client already exists: ${full_name}"
99 + return 1
100 + fi
101 + }
102 +
103 + # ============================================
104 + # Display helpers
105 + # ============================================
106 +
107 + function cmd::add::is_mobile() {
108 + local type="$1"
109 + [[ "$type" == "phone" || "$type" == "tablet" ]]
110 + }
111 +
112 + # ============================================
113 + # Run
114 + # ============================================
115 +
116 + function cmd::add::run() {
117 + local name=""
118 + local type=""
119 + local subtype=""
120 + local rule=""
121 + local ip=""
122 + local tunnel=""
123 + local guest=false
124 + local presets=()
125 + local show_config=false
126 + local show_qr=false
127 +
128 + # Parse flags
129 + while [[ $# -gt 0 ]]; do
130 + case "$1" in
131 + --name) name="$2"; shift 2 ;;
132 + --type) type="$2"; shift 2 ;;
133 + --subtype) subtype="$2"; shift 2 ;;
134 + --rule) rule="$2"; shift 2 ;;
135 + --ip) ip="$2"; shift 2 ;;
136 + --preset) presets+=("$2"); shift 2 ;;
137 + --guest) guest=true; shift ;;
138 + --tunnel) tunnel="$2"; shift 2 ;;
139 + --show-config) show_config=true; shift ;;
140 + --show-qr) show_qr=true; shift ;;
141 + --help) cmd::add::help; return ;;
142 + *)
143 + log::error "Unknown flag: $1"
144 + cmd::add::help
145 + return 1
146 + ;;
147 + esac
148 + done
149 +
150 + # --guest shorthand
151 + if $guest; then
152 + type="guest"
153 + fi
154 +
155 + # Resolve guest subtype
156 + local effective_type="$type"
157 + if [[ "$type" == "guest" && -n "$subtype" ]]; then
158 + # Validate subtype
159 + local valid_subtypes="desktop laptop phone tablet"
160 + if ! echo "$valid_subtypes" | grep -qw "$subtype"; then
161 + log::error "Invalid subtype: ${subtype} (valid: desktop, laptop, phone, tablet)"
162 + return 1
163 + fi
164 + effective_type="guest-${subtype}"
165 + fi
166 +
167 + # Build full client name
168 + local full_name="${type}-${name}"
169 +
170 + # Validate
171 + cmd::add::validate "$name" "$type" "$ip" "$tunnel" || return 1
172 +
173 + # Resolve tunnel mode — flag > device default
174 + if [[ -z "$tunnel" ]]; then
175 + tunnel=$(config::default_tunnel_for "$type")
176 + fi
177 +
178 + # Determine rule — explicit flag > type default
179 + if [[ -z "$rule" ]]; then
180 + if config::is_guest_type "$type"; then
181 + rule="guest"
182 + else
183 + rule="user"
184 + fi
185 + fi
186 +
187 + # Validate rule if specified
188 + if ! rule::exists "$rule"; then
189 + log::error "Rule not found: ${rule}"
190 + return 1
191 + fi
192 +
193 + local allowed_ips
194 + allowed_ips=$(config::allowed_ips_for "$effective_type" "$tunnel") || return 1
195 +
196 + log::section "Adding client: ${full_name}"
197 +
198 + # Auto-assign IP if not provided
199 + if [[ -z "$ip" ]]; then
200 + ip=$(ip::next_for_type "$effective_type") || return 1
201 + fi
202 +
203 + log::wg_add "Name: ${full_name}"
204 + log::wg_add "Type: ${type}"
205 + log::wg_add "IP: ${ip}"
206 + log::wg_add "Tunnel: ${tunnel} (${allowed_ips})"
207 +
208 + # Generate keys
209 + keys::generate_pair "$full_name" || return 1
210 +
211 + # Create client config
212 + peers::create_client_config "$full_name" "$effective_type" "$ip" "$allowed_ips" || return 1
213 +
214 + # Store subtype in meta
215 + if [[ -n "$subtype" ]]; then
216 + peers::set_meta "$full_name" "subtype" "$subtype"
217 + fi
218 +
219 + # Add peer to server config
220 + local public_key
221 + public_key=$(keys::public "$full_name") || return 1
222 + peers::add_to_server "$full_name" "$public_key" "$ip" || return 1
223 +
224 + log::wg_add "Rule: ${rule:-none}"
225 +
226 + # Apply presets
227 + for preset in "${presets[@]}"; do
228 + firewall::apply_preset "$preset" "${ip}" || return 1
229 + done
230 +
231 + # Apply rule
232 + if [[ -n "$rule" ]]; then
233 + rule::apply "$rule" "$ip" || return 1
234 + fi
235 +
236 + # Reload WireGuard
237 + peers::reload || return 1
238 +
239 + log::wg_success "Client added successfully: ${full_name} (${ip}) [${tunnel} tunnel]"
240 +
241 + # Show QR for mobile by default, config for desktop/laptop
242 + local display_type="${subtype:-$type}"
243 +
244 + if cmd::add::is_mobile "$display_type"; then
245 + keys::qr "$full_name"
246 + else
247 + log::section "Client Config"
248 + cat "$(ctx::clients)/${full_name}.conf"
249 + fi
250 + }
Daha yeni Daha eski