Last active 3 weeks ago

beanman109 revised this gist 3 weeks ago. Go to revision

1 file changed, 32 insertions, 7 deletions

0 - readme.md

@@ -1,14 +1,39 @@
1 - Initial Setup:
1 + ## Initial Setup
2 +
3 + ```sh
2 4 curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/initial-setup.sh | sh
3 - or
5 + ```
6 +
7 + **or**
8 +
9 + ```sh
4 10 wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/initial-setup.sh | sh
11 + ```
5 12
6 - Fail2ban Setup:
13 + ---
14 +
15 + ## Fail2ban Setup
16 +
17 + ```sh
7 18 curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/fail2ban-setup.sh | sh
8 - or
19 + ```
20 +
21 + **or**
22 +
23 + ```sh
9 24 wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/fail2ban-setup.sh | sh
25 + ```
26 +
27 + ---
28 +
29 + ## Squid Setup
10 30
11 - Squid Setup:
31 + ```sh
12 32 curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/squid-setup.sh | sh
13 - or
14 - wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/squid-setup.sh | sh
33 + ```
34 +
35 + **or**
36 +
37 + ```sh
38 + wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/squid-setup.sh | sh
39 + ```

beanman109 revised this gist 3 weeks ago. Go to revision

1 file changed, 14 insertions, 1 deletion

0 - readme.md

@@ -1 +1,14 @@
1 - Scripts for Alpine
1 + Initial Setup:
2 + curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/initial-setup.sh | sh
3 + or
4 + wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/initial-setup.sh | sh
5 +
6 + Fail2ban Setup:
7 + curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/fail2ban-setup.sh | sh
8 + or
9 + wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/fail2ban-setup.sh | sh
10 +
11 + Squid Setup:
12 + curl -sL https://beanman.net/gist/beanman109/alpine/raw/HEAD/squid-setup.sh | sh
13 + or
14 + wget -qO- https://beanman.net/gist/beanman109/alpine/raw/HEAD/squid-setup.sh | sh

beanman109 revised this gist 3 weeks ago. Go to revision

1 file changed, 0 insertions, 0 deletions

readme.md renamed to 0 - readme.md

File renamed without changes

beanman109 revised this gist 3 weeks ago. Go to revision

3 files changed, 761 insertions

fail2ban-setup.sh(file created)

@@ -0,0 +1,61 @@
1 + #!/bin/sh
2 +
3 + # Ensure the script is run as root
4 + if [ "$(id -u)" -ne 0 ]; then
5 + echo "Error: This script must be run as root." >&2
6 + exit 1
7 + fi
8 +
9 + echo "--- 1. Installing Fail2ban, Rsyslog, and Iptables ---"
10 + apk update
11 + # iptables is required for Fail2ban's default banning actions
12 + apk add fail2ban rsyslog iptables
13 +
14 + echo "--- 2. Ripping out BusyBox Syslog and configuring Rsyslog ---"
15 + # Stop and remove the default Alpine logger
16 + rc-service syslog stop 2>/dev/null
17 + rc-update del syslog boot 2>/dev/null
18 +
19 + # Enable Rsyslog
20 + rc-update add rsyslog boot
21 +
22 + # Force Rsyslog to use the traditional date format (must be at the absolute top of the config)
23 + sed -i '/\$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat/d' /etc/rsyslog.conf
24 + echo '$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat' > /tmp/rsyslog-new.conf
25 + cat /etc/rsyslog.conf >> /tmp/rsyslog-new.conf
26 + mv /tmp/rsyslog-new.conf /etc/rsyslog.conf
27 +
28 + # Start Rsyslog
29 + rc-service rsyslog restart
30 +
31 + echo "--- 3. Creating Custom SSHD Filter ---"
32 + mkdir -p /etc/fail2ban/filter.d
33 + # This regex ignores Alpine/rsyslog prefix bloat and hunts directly for OpenSSH 9.8+ session failures
34 + cat << 'EOF' > /etc/fail2ban/filter.d/sshd-nuclear.conf
35 + [Definition]
36 + failregex = ^.*(?:sshd|sshd-session)(?:\[\d+\])?: (?:Failed password for|Invalid user) .*? from <HOST>.*$
37 + ignoreregex =
38 + EOF
39 +
40 + echo "--- 4. Configuring jail.local ---"
41 + cat << 'EOF' > /etc/fail2ban/jail.local
42 + [DEFAULT]
43 + bantime = 1h
44 + findtime = 10m
45 + maxretry = 5
46 +
47 + [sshd]
48 + enabled = true
49 + port = ssh
50 + filter = sshd-nuclear
51 + logpath = /var/log/messages
52 + # Force polling to prevent silent failures on Alpine
53 + backend = polling
54 + EOF
55 +
56 + echo "--- 5. Enabling and Starting Fail2ban ---"
57 + rc-update add fail2ban default
58 + rc-service fail2ban restart
59 +
60 + echo ""
61 + echo "Fail2ban install complete. Check Fail2ban is now actively monitoring /var/log/messages."

initial-setup.sh(file created)

@@ -0,0 +1,83 @@
1 + #!/bin/sh
2 +
3 + # Ensure the script is run as root
4 + if [ "$(id -u)" -ne 0 ]; then
5 + echo "Error: This script must be run as root."
6 + exit 1
7 + fi
8 +
9 + echo "--- Starting Alpine Linux Initial Setup ---"
10 +
11 + # 1. Point to latest-stable and enable the community repository
12 + echo "-> Configuring APK repositories..."
13 + sed -i 's/v[0-9]\.[0-9]*/latest-stable/g' /etc/apk/repositories
14 + sed -i '/community/s/^#//' /etc/apk/repositories
15 +
16 + # 2. Update and upgrade the system
17 + echo "-> Updating and upgrading system packages..."
18 + apk update
19 + apk upgrade -a
20 +
21 + # 3. Install requested and essential utilities
22 + echo "-> Installing utilities, security tools, and rsyslog..."
23 + apk add btop chrony tzdata fail2ban openssh iptables curl nano rsyslog
24 +
25 + # 4. Configure Timezone
26 + echo "-> Configuring timezone (Australia/Brisbane)..."
27 + setup-timezone -z Australia/Brisbane
28 +
29 + # 5. Configure and enable Chrony (NTP)
30 + echo "-> Enabling and starting Chrony..."
31 + rc-update add chronyd default
32 + rc-service chronyd restart
33 +
34 + # 6. Configure and enable OpenSSH
35 + echo "-> Enabling and starting SSHD..."
36 + rc-update add sshd default
37 + rc-service sshd restart
38 +
39 + # 7. Configure Logging (Rsyslog overriding Busybox)
40 + echo "-> Swapping default syslog for rsyslog with traditional formatting..."
41 + rc-service syslog stop 2>/dev/null
42 + rc-update del syslog boot 2>/dev/null
43 + rc-update add rsyslog boot
44 +
45 + # Force Rsyslog to use the traditional date format required by Fail2ban
46 + sed -i '/\$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat/d' /etc/rsyslog.conf
47 + echo '$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat' > /tmp/rsyslog-new.conf
48 + cat /etc/rsyslog.conf >> /tmp/rsyslog-new.conf
49 + mv /tmp/rsyslog-new.conf /etc/rsyslog.conf
50 +
51 + rc-service rsyslog restart
52 +
53 + # 8. Configure Fail2Ban for OpenSSH
54 + echo "-> Configuring Fail2Ban for SSH..."
55 +
56 + # Create the custom brute-force SSH filter
57 + mkdir -p /etc/fail2ban/filter.d
58 + cat << 'EOF' > /etc/fail2ban/filter.d/sshd-nuclear.conf
59 + [Definition]
60 + failregex = ^.*(?:sshd|sshd-session)(?:\[\d+\])?: (?:Failed password for|Invalid user) .*? from <HOST>.*$
61 + ignoreregex =
62 + EOF
63 +
64 + # Create the local jail configuration
65 + cat << 'EOF' > /etc/fail2ban/jail.d/sshd.local
66 + [sshd]
67 + enabled = true
68 + port = ssh
69 + filter = sshd-nuclear
70 + logpath = /var/log/messages
71 + # Force polling so Alpine doesn't silently fail file watches
72 + backend = polling
73 + maxretry = 5
74 + bantime = 3600
75 + findtime = 600
76 + EOF
77 +
78 + # Enable and start Fail2Ban
79 + rc-update add fail2ban default
80 + rc-service fail2ban restart
81 +
82 + echo "--- Alpine Linux Initial Setup Complete! ---"
83 + echo "It is highly recommended to reboot the system to ensure all kernel and package upgrades take effect."

squid-setup.sh(file created)

@@ -0,0 +1,617 @@
1 + #!/bin/sh
2 + set -eu
3 +
4 + # ============================================================
5 + # Interactive Squid HTTPS Proxy Installer with Let's Encrypt
6 + # Alpine Linux Edition (OpenRC)
7 + #
8 + # Creates:
9 + # Firefox/FoxyProxy -> HTTPS proxy -> Squid -> Internet
10 + #
11 + # IMPORTANT:
12 + # In FoxyProxy, use the DOMAIN NAME, not the IP address.
13 + # ============================================================
14 +
15 + RED="\033[31m"
16 + GREEN="\033[32m"
17 + YELLOW="\033[33m"
18 + BLUE="\033[34m"
19 + RESET="\033[0m"
20 +
21 + log() { printf "${GREEN}[OK]${RESET} %s\n" "$*"; }
22 + info() { printf "${BLUE}[INFO]${RESET} %s\n" "$*"; }
23 + warn() { printf "${YELLOW}[WARN]${RESET} %s\n" "$*"; }
24 + die() { printf "${RED}[ERROR]${RESET} %s\n" "$*" >&2; exit 1; }
25 +
26 + SQUID_USER="squid"
27 + SQUID_GROUP="squid"
28 + STOPPED_SERVICES=""
29 +
30 + require_root() {
31 + if [ "$(id -u)" -ne 0 ]; then
32 + die "Run this script as root."
33 + fi
34 + }
35 +
36 + ask() {
37 + local prompt="$1"
38 + local default="${2:-}"
39 + local value
40 +
41 + # Output the prompt to stderr (>&2) so it displays on the screen
42 + # even when the function's output is being captured by a variable.
43 + if [ -n "$default" ]; then
44 + printf "%s [%s]: " "$prompt" "$default" >&2
45 + else
46 + printf "%s: " "$prompt" >&2
47 + fi
48 + read -r value
49 + echo "${value:-$default}"
50 + }
51 +
52 + ask_password_confirmed() {
53 + local pass1 pass2
54 +
55 + while true; do
56 + printf "Proxy password: " >&2
57 + stty -echo
58 + read -r pass1
59 + stty echo
60 + printf '\n' >&2
61 +
62 + printf "Confirm proxy password: " >&2
63 + stty -echo
64 + read -r pass2
65 + stty echo
66 + printf '\n' >&2
67 +
68 + if [ -z "$pass1" ]; then
69 + warn "Password cannot be empty." >&2
70 + continue
71 + fi
72 +
73 + if [ "$pass1" != "$pass2" ]; then
74 + warn "Passwords do not match." >&2
75 + continue
76 + fi
77 +
78 + printf '%s' "$pass1"
79 + return 0
80 + done
81 + }
82 +
83 + validate_domain() {
84 + local domain="$1"
85 +
86 + if ! echo "$domain" | grep -qE '^[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'; then
87 + die "Invalid domain: $domain"
88 + fi
89 +
90 + if echo "$domain" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
91 + die "Do not use an IP address. Use a real hostname, e.g. proxy.example.com"
92 + fi
93 + }
94 +
95 + validate_port() {
96 + local port="$1"
97 +
98 + if ! echo "$port" | grep -qE '^[0-9]+$'; then
99 + die "Invalid port: $port"
100 + fi
101 +
102 + if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
103 + die "Port must be between 1 and 65535."
104 + fi
105 + }
106 +
107 + detect_proxy_user_group() {
108 + if id squid >/dev/null 2>&1; then
109 + SQUID_USER="squid"
110 + elif id proxy >/dev/null 2>&1; then
111 + SQUID_USER="proxy"
112 + else
113 + SQUID_USER="squid"
114 + fi
115 +
116 + if getent group squid >/dev/null 2>&1; then
117 + SQUID_GROUP="squid"
118 + elif getent group proxy >/dev/null 2>&1; then
119 + SQUID_GROUP="proxy"
120 + else
121 + SQUID_GROUP="$SQUID_USER"
122 + fi
123 + }
124 +
125 + install_packages() {
126 + info "Installing required packages via apk..."
127 +
128 + apk update
129 + apk add squid apache2-utils certbot openssl curl ca-certificates bind-tools iptables
130 +
131 + log "Packages installed."
132 + }
133 +
134 + check_squid_openssl() {
135 + info "Checking Squid OpenSSL support..."
136 +
137 + if squid -v 2>/dev/null | grep -qi openssl; then
138 + log "Squid appears to have OpenSSL support."
139 + else
140 + warn "Could not confirm OpenSSL support from squid -v."
141 + warn "Alpine's default squid should support it, but check logs if https_port fails."
142 + fi
143 + }
144 +
145 + check_dns() {
146 + local domain="$1"
147 +
148 + info "Checking DNS for $domain..."
149 +
150 + local resolved_v4
151 + local resolved_v6
152 +
153 + resolved_v4="$(dig +short A "$domain" | tail -n1 || true)"
154 + resolved_v6="$(dig +short AAAA "$domain" | tail -n1 || true)"
155 +
156 + if [ -z "$resolved_v4" ] && [ -z "$resolved_v6" ]; then
157 + warn "No A or AAAA record found for $domain."
158 + warn "Let's Encrypt will fail unless this hostname points to this server."
159 + printf "Continue anyway? [y/N]: "
160 + read -r yn
161 + if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
162 + die "Stopped."
163 + fi
164 + else
165 + if [ -n "$resolved_v4" ]; then
166 + log "$domain A record: $resolved_v4"
167 + fi
168 +
169 + if [ -n "$resolved_v6" ]; then
170 + log "$domain AAAA record: $resolved_v6"
171 + else
172 + warn "$domain has no AAAA record. That is fine if you only want IPv4."
173 + fi
174 + fi
175 +
176 + return 0
177 + }
178 +
179 + open_firewall() {
180 + local port="$1"
181 +
182 + info "Attempting to open firewall ports 80 and $port..."
183 +
184 + if command -v iptables >/dev/null 2>&1; then
185 + iptables -C INPUT -p tcp --dport 80 -j ACCEPT 2>/dev/null || iptables -I INPUT -p tcp --dport 80 -j ACCEPT
186 + iptables -C INPUT -p tcp --dport "$port" -j ACCEPT 2>/dev/null || iptables -I INPUT -p tcp --dport "$port" -j ACCEPT
187 + log "Temporary iptables rules added."
188 + warn "iptables rules may not persist after reboot depending on your Alpine configuration (awall/iptables-save)."
189 + fi
190 + }
191 +
192 + stop_port_80_services_if_needed() {
193 + STOPPED_SERVICES=""
194 +
195 + if netstat -tlnp | grep -qE '(:80[[:space:]]|:80$)'; then
196 + warn "Something appears to be using port 80."
197 + echo
198 + netstat -tlnp | grep ':80' || true
199 + echo
200 +
201 + printf "Temporarily stop nginx/apache2/caddy if running so Certbot can use port 80? [Y/n]: "
202 + read -r yn
203 + yn="${yn:-Y}"
204 +
205 + if [ "$yn" = "y" ] || [ "$yn" = "Y" ]; then
206 + for svc in nginx apache2 caddy; do
207 + if rc-service "$svc" status >/dev/null 2>&1; then
208 + rc-service "$svc" stop
209 + STOPPED_SERVICES="$STOPPED_SERVICES $svc"
210 + warn "Stopped $svc temporarily."
211 + fi
212 + done
213 + fi
214 + fi
215 + }
216 +
217 + restart_stopped_services() {
218 + if [ -n "$STOPPED_SERVICES" ]; then
219 + info "Restarting services stopped for Certbot..."
220 +
221 + for svc in $STOPPED_SERVICES; do
222 + rc-service "$svc" start || warn "Could not restart $svc."
223 + done
224 + fi
225 + }
226 +
227 + get_certificate() {
228 + local domain="$1"
229 + local email="$2"
230 +
231 + if [ -f "/etc/letsencrypt/live/$domain/fullchain.pem" ] && [ -f "/etc/letsencrypt/live/$domain/privkey.pem" ]; then
232 + log "Existing Let's Encrypt cert found for $domain."
233 + printf "Use existing certificate? [Y/n]: "
234 + read -r yn
235 + yn="${yn:-Y}"
236 +
237 + if [ "$yn" = "y" ] || [ "$yn" = "Y" ]; then
238 + return 0
239 + fi
240 + fi
241 +
242 + stop_port_80_services_if_needed
243 +
244 + info "Requesting Let's Encrypt certificate for $domain..."
245 +
246 + if [ -n "$email" ]; then
247 + certbot certonly --standalone \
248 + -d "$domain" \
249 + --non-interactive \
250 + --agree-tos \
251 + --email "$email"
252 + else
253 + certbot certonly --standalone \
254 + -d "$domain" \
255 + --non-interactive \
256 + --agree-tos \
257 + --register-unsafely-without-email
258 + fi
259 +
260 + restart_stopped_services
261 +
262 + log "Certificate issued."
263 + }
264 +
265 + copy_certs() {
266 + local domain="$1"
267 +
268 + info "Copying certificate files into /etc/squid/certs..."
269 +
270 + mkdir -p /etc/squid/certs
271 +
272 + cp "/etc/letsencrypt/live/$domain/fullchain.pem" /etc/squid/certs/proxy-fullchain.pem
273 + cp "/etc/letsencrypt/live/$domain/privkey.pem" /etc/squid/certs/proxy-privkey.pem
274 +
275 + chown -R "$SQUID_USER:$SQUID_GROUP" /etc/squid/certs
276 + chmod 644 /etc/squid/certs/proxy-fullchain.pem
277 + chmod 600 /etc/squid/certs/proxy-privkey.pem
278 +
279 + log "Certificates copied."
280 + }
281 +
282 + create_auth() {
283 + local username="$1"
284 + local password="$2"
285 +
286 + info "Creating Squid username/password auth..."
287 +
288 + touch /etc/squid/passwd
289 + chown "$SQUID_USER:$SQUID_GROUP" /etc/squid/passwd
290 + chmod 640 /etc/squid/passwd
291 +
292 + printf '%s\n' "$password" | htpasswd -m -i /etc/squid/passwd "$username" >/dev/null
293 +
294 + chown "$SQUID_USER:$SQUID_GROUP" /etc/squid/passwd
295 + chmod 640 /etc/squid/passwd
296 +
297 + log "Proxy user created: $username"
298 + }
299 +
300 + test_auth_helper() {
301 + local username="$1"
302 + local password="$2"
303 +
304 + info "Testing Squid auth helper directly..."
305 +
306 + local result
307 + result="$(printf '%s %s\n' "$username" "$password" | /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd || true)"
308 +
309 + if echo "$result" | grep -q '^OK'; then
310 + log "Squid auth helper accepted the username/password."
311 + else
312 + warn "Squid auth helper did not accept the username/password."
313 + echo "Auth helper output:"
314 + echo "$result"
315 + die "Stopping because proxy auth would fail."
316 + fi
317 + }
318 +
319 + write_squid_config() {
320 + local domain="$1"
321 + local port="$2"
322 + local syntax="$3"
323 +
324 + local https_line
325 +
326 + if [ "$syntax" = "new" ]; then
327 + https_line="https_port $port tls-cert=/etc/squid/certs/proxy-fullchain.pem tls-key=/etc/squid/certs/proxy-privkey.pem"
328 + else
329 + https_line="https_port $port cert=/etc/squid/certs/proxy-fullchain.pem key=/etc/squid/certs/proxy-privkey.pem"
330 + fi
331 +
332 + info "Writing Squid config using syntax: $syntax"
333 +
334 + if [ -f /etc/squid/squid.conf ] && [ ! -f /etc/squid/squid.conf.bak-before-https-proxy ]; then
335 + cp /etc/squid/squid.conf /etc/squid/squid.conf.bak-before-https-proxy
336 + log "Backed up original config to /etc/squid/squid.conf.bak-before-https-proxy"
337 + fi
338 +
339 + cat > /etc/squid/squid.conf <<EOF
340 + # ============================================================
341 + # Squid HTTPS/TLS encrypted forward proxy
342 + # Generated by setup-https-squid-proxy.sh
343 + #
344 + # Domain: $domain
345 + # Port: $port
346 + #
347 + # IMPORTANT:
348 + # In FoxyProxy, use host "$domain", not the server IP.
349 + # ============================================================
350 +
351 + $https_line
352 +
353 + auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
354 + auth_param basic realm HTTPS Proxy
355 + auth_param basic credentialsttl 2 hours
356 +
357 + acl authenticated proxy_auth REQUIRED
358 +
359 + acl SSL_ports port 443
360 + acl Safe_ports port 80
361 + acl Safe_ports port 443
362 + acl Safe_ports port 1025-65535
363 + acl CONNECT method CONNECT
364 +
365 + http_access deny !Safe_ports
366 + http_access deny CONNECT !SSL_ports
367 + http_access allow authenticated
368 + http_access deny all
369 +
370 + cache deny all
371 + cache_mem 8 MB
372 + maximum_object_size 0 KB
373 +
374 + via off
375 + forwarded_for delete
376 + request_header_access X-Forwarded-For deny all
377 + request_header_access Via deny all
378 + request_header_access Cache-Control deny all
379 +
380 + access_log /var/log/squid/access.log
381 + cache_log /var/log/squid/cache.log
382 +
383 + cache_effective_user $SQUID_USER
384 + cache_effective_group $SQUID_GROUP
385 +
386 + visible_hostname $domain
387 + EOF
388 + }
389 +
390 + find_working_squid_syntax() {
391 + local domain="$1"
392 + local port="$2"
393 +
394 + write_squid_config "$domain" "$port" "new"
395 +
396 + if squid -k parse >/tmp/squid-parse.log 2>&1; then
397 + log "Squid config parsed successfully with tls-cert/tls-key syntax."
398 + return 0
399 + fi
400 +
401 + warn "tls-cert/tls-key syntax failed. Trying older cert/key syntax..."
402 + cat /tmp/squid-parse.log || true
403 +
404 + write_squid_config "$domain" "$port" "old"
405 +
406 + if squid -k parse >/tmp/squid-parse.log 2>&1; then
407 + log "Squid config parsed successfully with cert/key syntax."
408 + return 0
409 + fi
410 +
411 + cat /tmp/squid-parse.log || true
412 + die "Squid could not parse either HTTPS config style. Your Squid build may not support https_port/OpenSSL."
413 + }
414 +
415 + write_renewal_hook() {
416 + local domain="$1"
417 +
418 + info "Creating Certbot renewal hook..."
419 +
420 + mkdir -p /etc/letsencrypt/renewal-hooks/deploy
421 +
422 + cat > /etc/letsencrypt/renewal-hooks/deploy/squid-cert-copy.sh <<EOF
423 + #!/bin/sh
424 + set -e
425 +
426 + DOMAIN="$domain"
427 +
428 + SRC_CERT="/etc/letsencrypt/live/\$DOMAIN/fullchain.pem"
429 + SRC_KEY="/etc/letsencrypt/live/\$DOMAIN/privkey.pem"
430 +
431 + DST_DIR="/etc/squid/certs"
432 + DST_CERT="\$DST_DIR/proxy-fullchain.pem"
433 + DST_KEY="\$DST_DIR/proxy-privkey.pem"
434 +
435 + mkdir -p "\$DST_DIR"
436 +
437 + cp "\$SRC_CERT" "\$DST_CERT"
438 + cp "\$SRC_KEY" "\$DST_KEY"
439 +
440 + chown $SQUID_USER:$SQUID_GROUP "\$DST_CERT" "\$DST_KEY"
441 + chmod 644 "\$DST_CERT"
442 + chmod 600 "\$DST_KEY"
443 +
444 + rc-service squid reload || rc-service squid restart
445 + EOF
446 +
447 + chmod +x /etc/letsencrypt/renewal-hooks/deploy/squid-cert-copy.sh
448 +
449 + log "Renewal hook created at /etc/letsencrypt/renewal-hooks/deploy/squid-cert-copy.sh"
450 + }
451 +
452 + restart_squid_cleanly() {
453 + info "Restarting Squid cleanly via OpenRC..."
454 +
455 + rc-service squid stop >/dev/null 2>&1 || true
456 + sleep 2
457 +
458 + pkill -9 squid >/dev/null 2>&1 || true
459 + sleep 1
460 +
461 + rc-service squid start
462 +
463 + if rc-service squid status >/dev/null 2>&1; then
464 + rc-update add squid default >/dev/null 2>&1 || true
465 + log "Squid is running and enabled on boot."
466 + else
467 + rc-service squid status || true
468 + tail -100 /var/log/squid/cache.log || true
469 + die "Squid failed to start."
470 + fi
471 + }
472 +
473 + test_listener() {
474 + local port="$1"
475 +
476 + info "Checking if Squid is listening on port $port..."
477 +
478 + if netstat -tlnp | grep -q ":$port "; then
479 + log "Something is listening on port $port:"
480 + netstat -tlnp | grep ":$port " || true
481 + else
482 + warn "Port $port does not appear in netstat output."
483 + fi
484 + }
485 +
486 + test_proxy() {
487 + local domain="$1"
488 + local port="$2"
489 + local username="$3"
490 + local password="$4"
491 +
492 + info "Testing proxy with curl..."
493 +
494 + set +e
495 + local result
496 + result="$(curl -4 -sS --max-time 30 \
497 + --proxy "https://$domain:$port" \
498 + --proxy-user "$username:$password" \
499 + https://chy.li/ip 2>&1)"
500 + local rc=$?
501 + set -e
502 +
503 + if [ $rc -eq 0 ]; then
504 + log "Proxy test succeeded. Outgoing IP:"
505 + echo "$result"
506 + else
507 + warn "Curl proxy test failed."
508 + echo "$result"
509 + echo
510 + warn "Check logs:"
511 + echo " tail -f /var/log/squid/cache.log"
512 + echo " tail -f /var/log/squid/access.log"
513 + fi
514 + }
515 +
516 + print_summary() {
517 + local domain="$1"
518 + local port="$2"
519 + local username="$3"
520 +
521 + echo
522 + echo "============================================================"
523 + echo " HTTPS Squid Proxy Setup Complete"
524 + echo "============================================================"
525 + echo
526 + echo "FoxyProxy settings:"
527 + echo
528 + echo " Proxy Type: HTTPS"
529 + echo " Host: $domain"
530 + echo " Port: $port"
531 + echo " Username: $username"
532 + echo " Password: the password you entered"
533 + echo
534 + echo "IMPORTANT:"
535 + echo " Use the hostname \"$domain\" in FoxyProxy."
536 + echo " Do NOT use the server IP address."
537 + echo
538 + echo "Test command:"
539 + echo
540 + echo " curl -v \\"
541 + echo " --proxy \"https://$domain:$port\" \\"
542 + echo " --proxy-user \"$username:YOUR_PASSWORD\" \\"
543 + echo " https://chy.li/ip"
544 + echo
545 + echo "Useful logs:"
546 + echo
547 + echo " tail -f /var/log/squid/cache.log"
548 + echo " tail -f /var/log/squid/access.log"
549 + echo
550 + echo "============================================================"
551 + }
552 +
553 + main() {
554 + require_root
555 +
556 + echo
557 + echo "============================================================"
558 + echo " Interactive Squid HTTPS Proxy + Let's Encrypt Installer"
559 + echo " Alpine Linux Edition"
560 + echo "============================================================"
561 + echo
562 +
563 + DOMAIN="$(ask "Proxy domain, e.g. proxy.example.com")"
564 + validate_domain "$DOMAIN"
565 +
566 + PORT="$(ask "HTTPS proxy port" "8443")"
567 + validate_port "$PORT"
568 +
569 + USERNAME="$(ask "Proxy username" "proxyuser")"
570 + if [ -z "$USERNAME" ]; then
571 + die "Username cannot be empty."
572 + fi
573 +
574 + PASSWORD="$(ask_password_confirmed)"
575 +
576 + EMAIL="$(ask "Email for Let's Encrypt renewal notices, or leave blank" "")"
577 +
578 + echo
579 + echo "Summary:"
580 + echo " Domain: $DOMAIN"
581 + echo " Port: $PORT"
582 + echo " Username: $USERNAME"
583 + if [ -n "$EMAIL" ]; then
584 + echo " LE Email: $EMAIL"
585 + else
586 + echo " LE Email: none"
587 + fi
588 + echo
589 +
590 + printf "Continue with install? [Y/n]: "
591 + read -r confirm
592 + confirm="${confirm:-Y}"
593 + if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
594 + die "Cancelled."
595 + fi
596 +
597 + install_packages
598 + detect_proxy_user_group
599 +
600 + info "Detected Squid user/group: $SQUID_USER:$SQUID_GROUP"
601 +
602 + check_squid_openssl
603 + check_dns "$DOMAIN"
604 + open_firewall "$PORT"
605 + get_certificate "$DOMAIN" "$EMAIL"
606 + copy_certs "$DOMAIN"
607 + create_auth "$USERNAME" "$PASSWORD"
608 + test_auth_helper "$USERNAME" "$PASSWORD"
609 + find_working_squid_syntax "$DOMAIN" "$PORT"
610 + write_renewal_hook "$DOMAIN"
611 + restart_squid_cleanly
612 + test_listener "$PORT"
613 + test_proxy "$DOMAIN" "$PORT" "$USERNAME" "$PASSWORD"
614 + print_summary "$DOMAIN" "$PORT" "$USERNAME"
615 + }
616 +
617 + main "$@"

beanman109 revised this gist 3 weeks ago. Go to revision

1 file changed, 1 insertion

readme.md(file created)

@@ -0,0 +1 @@
1 + Scripts for Alpine
Newer Older