Son aktivite 1 month ago

nuno bu gisti düzenledi 1 month ago. Düzenlemeye git

1 file changed, 300 insertions

gistfile1.txt(dosya oluşturuldu)

@@ -0,0 +1,300 @@
1 + #!/usr/bin/env bash
2 +
3 + # ============================================
4 + # Rule File Parsing
5 + # ============================================
6 +
7 + function rule::exists() {
8 + local name="$1"
9 + [[ -f "$(ctx::rule::path "${name}.rule")" ]]
10 + }
11 +
12 + function rule::require_exists() {
13 + local name="$1"
14 + if ! rule::exists "$name"; then
15 + log::error "Rule not found: ${name}"
16 + return 1
17 + fi
18 + }
19 +
20 + function rule::get() {
21 + local name="$1" key="$2"
22 + json::get "$(ctx::rule::path "${name}.rule")" "$key"
23 + }
24 +
25 + function rule::get_all() {
26 + local name="$1"
27 + local rule_file
28 + rule_file="$(ctx::rule::path "${name}.rule")"
29 + cat "$rule_file"
30 + }
31 +
32 + function rule::is_applied() {
33 + local rule_name="$1"
34 + local client_ip="$2"
35 +
36 + # Try first block_ports entry
37 + local first_port
38 + first_port=$(rule::get "$rule_name" "block_ports" | head -1)
39 + if [[ -n "$first_port" ]]; then
40 + local target port proto
41 + IFS=":" read -r target port proto <<< "$first_port"
42 + proto="${proto:-tcp}"
43 + iptables -C FORWARD -s "$client_ip" -d "$target" -p "$proto" --dport "$port" -j DROP 2>/dev/null
44 + return $?
45 + fi
46 +
47 + # Fall back to first block_ips entry
48 + local first_ip
49 + first_ip=$(rule::get "$rule_name" "block_ips" | head -1)
50 + if [[ -n "$first_ip" ]]; then
51 + iptables -C FORWARD -s "$client_ip" -d "$first_ip" -j DROP 2>/dev/null
52 + return $?
53 + fi
54 +
55 + # No rules to check (admin rule) — check allow_ports
56 + local first_allow
57 + first_allow=$(rule::get "$rule_name" "allow_ports" | head -1)
58 + if [[ -n "$first_allow" ]]; then
59 + local target port proto
60 + IFS=":" read -r target port proto <<< "$first_allow"
61 + proto="${proto:-tcp}"
62 + iptables -C FORWARD -s "$client_ip" -d "$target" -p "$proto" --dport "$port" -j ACCEPT 2>/dev/null
63 + return $?
64 + fi
65 +
66 + # Empty rule (admin) — never "applied" in iptables sense
67 + return 1
68 + }
69 +
70 + # ============================================
71 + # Rule Application
72 + # ============================================
73 +
74 + function rule::apply() {
75 + local rule_name="${1:?rule_name required}"
76 + local client_ip="${2:?client_ip required}"
77 + local peer_name="${3:-}" # optional, avoids find_by_ip call
78 +
79 + rule::require_exists "$rule_name" || return 1
80 +
81 + # Use provided peer_name or look it up
82 + if [[ -z "$peer_name" ]]; then
83 + peer_name=$(peers::find_by_ip "$client_ip")
84 + fi
85 +
86 + # Check if already applied
87 + if rule::is_applied "$rule_name" "$client_ip"; then
88 + log::wg "Rule '${rule_name}' already applied to: ${client_ip}"
89 +
90 + # Still update meta even if rules exist
91 + if [[ -n "$peer_name" ]]; then
92 + peers::set_meta "$peer_name" "rule" "$rule_name"
93 + fi
94 +
95 + return 0
96 + fi
97 +
98 + # Check if already applied
99 + local peer_name
100 + peer_name=$(peers::find_by_ip "$client_ip")
101 + if [[ -n "$peer_name" ]]; then
102 + # Check if already applied via iptables
103 + if rule::is_applied "$rule_name" "$client_ip"; then
104 + log::wg "Rule '${rule_name}' already applied to: ${client_ip}"
105 + return 0
106 + fi
107 + fi
108 +
109 + # Process block_ips
110 + while IFS= read -r block_ip; do
111 + [[ -z "$block_ip" ]] && continue
112 + fw::block_ip "$client_ip" "$block_ip"
113 + done < <(rule::get "$rule_name" "block_ips")
114 +
115 + # Process block_ports
116 + while IFS= read -r entry; do
117 + [[ -z "$entry" ]] && continue
118 + local target port proto
119 + IFS=":" read -r target port proto <<< "$entry"
120 + proto="${proto:-tcp}"
121 + fw::block_port "$client_ip" "$target" "$port" "$proto"
122 + done < <(rule::get "$rule_name" "block_ports")
123 +
124 + # Process allow_ips (inserted before blocks)
125 + while IFS= read -r allow_ip; do
126 + [[ -z "$allow_ip" ]] && continue
127 + fw::allow_ip "$client_ip" "$allow_ip"
128 + done < <(rule::get "$rule_name" "allow_ips")
129 +
130 + # allow_ports (inserted last = highest priority)
131 + while IFS= read -r entry; do
132 + [[ -z "$entry" ]] && continue
133 + local target port proto
134 + IFS=":" read -r target port proto <<< "$entry"
135 + proto="${proto:-tcp}"
136 + fw::allow_port "$client_ip" "$target" "$port" "$proto"
137 + done < <(rule::get "$rule_name" "allow_ports")
138 +
139 + # Persist rule assignment in meta
140 + if [[ -n "$peer_name" ]]; then
141 + peers::set_meta "$peer_name" "rule" "$rule_name"
142 + fi
143 +
144 + local dns_redirect
145 + dns_redirect=$(rule::get "$rule_name" "dns_redirect")
146 +
147 + if [[ "$dns_redirect" == "true" ]]; then
148 + local peer_subnet
149 + peer_subnet=$(peers::get_ip "$peer_name" | cut -d'.' -f1-3)
150 + # Only apply if not already in PREROUTING
151 + if ! iptables -t nat -C PREROUTING -i wg0 -s "${peer_subnet}.0/24" -p udp --dport 53 \
152 + -j DNAT --to-destination "$(config::dns):53" 2>/dev/null; then
153 + rule::apply_dns_redirect "${peer_subnet}.0/24"
154 + log::debug "dns_redirect: applied for ${peer_subnet}.0/24"
155 + else
156 + log::debug "dns_redirect: already applied for ${peer_subnet}.0/24"
157 + fi
158 + fi
159 +
160 + log::debug "Applied rule '${rule_name}' to: ${client_ip}"
161 + }
162 +
163 + function rule::unapply() {
164 + local rule_name="$1"
165 + local client_ip="$2"
166 +
167 + rule::require_exists "$rule_name" || return 1
168 +
169 + local peer_name
170 + peer_name=$(peers::find_by_ip "$client_ip")
171 +
172 + local subtype
173 + subtype=$(peers::get_meta "$peer_name" "subtype")
174 +
175 + local subnet
176 + subnet=$(config::subnet_for "$subtype")
177 +
178 + # Remove allow_ports first (reverse order of apply)
179 + while IFS= read -r entry; do
180 + [[ -z "$entry" ]] && continue
181 + local target port proto
182 + IFS=":" read -r target port proto <<< "$entry"
183 + proto="${proto:-tcp}"
184 + fw::unallow_port "$client_ip" "$target" "$port" "$proto"
185 + done < <(rule::get "$rule_name" "allow_ports")
186 +
187 + # Remove allow_ips
188 + while IFS= read -r allow_ip; do
189 + [[ -z "$allow_ip" ]] && continue
190 + fw::unallow_ip "$client_ip" "$allow_ip"
191 + done < <(rule::get "$rule_name" "allow_ips")
192 +
193 + # Remove block_ports
194 + while IFS= read -r entry; do
195 + [[ -z "$entry" ]] && continue
196 + local target port proto
197 + IFS=":" read -r target port proto <<< "$entry"
198 + proto="${proto:-tcp}"
199 + fw::unblock_port "$client_ip" "$target" "$port" "$proto"
200 + done < <(rule::get "$rule_name" "block_ports")
201 +
202 + # Remove block_ips
203 + while IFS= read -r block_ip; do
204 + [[ -z "$block_ip" ]] && continue
205 + fw::unblock_ip "$client_ip" "$block_ip"
206 + done < <(rule::get "$rule_name" "block_ips")
207 +
208 + # Remove DNS redirect if applicable
209 + local dns_redirect
210 + dns_redirect=$(rule::get "$rule_name" "dns_redirect")
211 + if [[ "$dns_redirect" == "true" ]]; then
212 + if [[ -z "$subtype" ]]; then
213 + local peer_type
214 + peer_type=$(peers::get_type "$peer_name") || true
215 + [[ -z "$peer_type" ]] && peer_type="phone" # fallback
216 + subnet=$(config::subnet_for "$peer_type")
217 + fi
218 +
219 + rule::remove_dns_redirect "${subnet}.0/24"
220 + fi
221 +
222 + # Clear rule from meta
223 + if [[ -n "$peer_name" ]]; then
224 + peers::set_meta "$peer_name" "rule" ""
225 + fi
226 +
227 + log::debug "Removed rule '${rule_name}' from: ${client_ip}"
228 + }
229 +
230 + function rule::reapply_all() {
231 + local rule_name="$1"
232 + rule::require_exists "$rule_name" || return 1
233 +
234 + local peers=()
235 + mapfile -t peers < <(peers::with_rule "$rule_name")
236 +
237 + [[ ${#peers[@]} -eq 0 ]] && return 0
238 +
239 + local count=0
240 + for peer_name in "${peers[@]}"; do
241 + local client_ip
242 + client_ip=$(peers::get_ip "$peer_name")
243 + [[ -z "$client_ip" ]] && continue
244 + rule::unapply "$rule_name" "$client_ip"
245 + rule::apply "$rule_name" "$client_ip" "$peer_name"
246 + (( count++ )) || true
247 + done
248 +
249 + log::wg_success "Rule '${rule_name}' re-applied to ${count} peers"
250 + }
251 +
252 + function rule::restore_all() {
253 + while IFS= read -r peer_name; do
254 + local rule_name
255 + rule_name=$(peers::get_meta "$peer_name" "rule")
256 + [[ -z "$rule_name" ]] && continue
257 +
258 + if ! rule::exists "$rule_name"; then
259 + log::wg_warning "Rule '${rule_name}' not found for peer '${peer_name}', skipping"
260 + continue
261 + fi
262 +
263 + local client_ip
264 + client_ip=$(peers::get_ip "$peer_name")
265 + [[ -z "$client_ip" ]] && continue
266 +
267 + rule::apply "$rule_name" "$client_ip"
268 + done < <(peers::all)
269 + log::wg "Rules restored for all peers"
270 + }
271 +
272 + # ============================================
273 + # Guest DNS Redirect (rule-level feature)
274 + # ============================================
275 +
276 + function rule::apply_dns_redirect() {
277 + local client_subnet="$1"
278 + local dns
279 + dns="$(config::dns)"
280 +
281 + iptables -t nat -A PREROUTING -i wg0 -s "$client_subnet" -p udp --dport 53 \
282 + ! -d "$dns" -j LOG --log-prefix "wgctl-dns-redirect: " --log-level 4
283 + iptables -t nat -A PREROUTING -i wg0 -s "$client_subnet" -p udp --dport 53 \
284 + -j DNAT --to-destination "${dns}:53"
285 + iptables -t nat -A PREROUTING -i wg0 -s "$client_subnet" -p tcp --dport 53 \
286 + -j DNAT --to-destination "${dns}:53"
287 + }
288 +
289 + function rule::remove_dns_redirect() {
290 + local client_subnet="$1"
291 + local dns
292 + dns="$(config::dns)"
293 +
294 + iptables -t nat -D PREROUTING -i wg0 -s "$client_subnet" -p udp --dport 53 \
295 + ! -d "$dns" -j LOG --log-prefix "wgctl-dns-redirect: " --log-level 4 2>/dev/null || true
296 + iptables -t nat -D PREROUTING -i wg0 -s "$client_subnet" -p udp --dport 53 \
297 + -j DNAT --to-destination "${dns}:53" 2>/dev/null || true
298 + iptables -t nat -D PREROUTING -i wg0 -s "$client_subnet" -p tcp --dport 53 \
299 + -j DNAT --to-destination "${dns}:53" 2>/dev/null || true
300 + }
Daha yeni Daha eski