415 lines
13 KiB
Bash
Executable File
415 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
# Fix script for current deployment issues
|
|
# Run this on the VPS to fix nginx configs, SSLH, and Let's Encrypt
|
|
|
|
set -e
|
|
|
|
# Don't exit on errors for some commands - we want to continue fixing
|
|
set +e
|
|
|
|
echo "=========================================="
|
|
echo "Fixing Deployment Issues"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
echo "=== Step 1: Ensuring Demo Page Exists ==="
|
|
mkdir -p /var/www/demo
|
|
chown -R www-data:www-data /var/www/demo 2>/dev/null || chown -R nginx:nginx /var/www/demo 2>/dev/null || true
|
|
|
|
if [ ! -f /var/www/demo/index.html ]; then
|
|
cat > /var/www/demo/index.html <<'HTML'
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Demo App Page</title>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100vh;
|
|
margin: 0;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
}
|
|
.container {
|
|
text-align: center;
|
|
padding: 2rem;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 10px;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
h1 {
|
|
margin: 0;
|
|
font-size: 3rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Demo app page</h1>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
HTML
|
|
echo "Created demo page"
|
|
else
|
|
echo "Demo page already exists"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Step 2: Creating Nginx Configuration Files ==="
|
|
mkdir -p /etc/nginx/sites-available
|
|
|
|
# Create sslh-proxy config
|
|
cat > /tmp/sslh-proxy.conf <<'EOF'
|
|
# Default server for root domain (HTTPS on port 443 via SSLH)
|
|
server {
|
|
listen 127.0.0.1:8444 ssl http2 default_server;
|
|
server_name _;
|
|
|
|
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
|
|
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
|
|
root /var/www/demo;
|
|
index index.html;
|
|
|
|
location / {
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
mv /tmp/sslh-proxy.conf /etc/nginx/sites-available/sslh-proxy
|
|
chmod 644 /etc/nginx/sites-available/sslh-proxy
|
|
echo "Created /etc/nginx/sites-available/sslh-proxy"
|
|
|
|
# Create acme-challenge config
|
|
cat > /tmp/acme-challenge.conf <<'EOF'
|
|
# HTTP server for Let's Encrypt ACME challenge
|
|
server {
|
|
listen 0.0.0.0:80 default_server;
|
|
listen [::]:80 default_server;
|
|
server_name _;
|
|
|
|
# Serve ACME challenge for Let's Encrypt
|
|
location /.well-known/acme-challenge/ {
|
|
root /var/www/html;
|
|
default_type text/plain;
|
|
access_log off;
|
|
}
|
|
|
|
# For root domain, serve demo page on HTTP
|
|
location / {
|
|
root /var/www/demo;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
mv /tmp/acme-challenge.conf /etc/nginx/sites-available/acme-challenge
|
|
chmod 644 /etc/nginx/sites-available/acme-challenge
|
|
echo "Created /etc/nginx/sites-available/acme-challenge"
|
|
|
|
echo ""
|
|
echo "=== Step 3: Stopping Nginx and Removing Default Configs ==="
|
|
systemctl stop nginx 2>/dev/null || true
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
rm -f /etc/nginx/sites-enabled/default.conf
|
|
rm -f /etc/nginx/sites-enabled/000-default
|
|
rm -f /etc/nginx/sites-enabled/000-default.conf
|
|
rm -f /etc/nginx/conf.d/default.conf 2>/dev/null || true
|
|
rm -f /usr/share/nginx/html/index.html /var/www/html/index.html 2>/dev/null || true
|
|
echo "Removed default nginx configs and HTML files"
|
|
|
|
echo ""
|
|
echo "=== Step 4: Enabling Nginx Sites ==="
|
|
ln -sf /etc/nginx/sites-available/acme-challenge /etc/nginx/sites-enabled/acme-challenge
|
|
ln -sf /etc/nginx/sites-available/sslh-proxy /etc/nginx/sites-enabled/sslh-proxy
|
|
echo "Enabled nginx sites"
|
|
|
|
echo ""
|
|
echo "=== Step 5: Testing Nginx Configuration ==="
|
|
nginx -t || { echo "ERROR: Nginx configuration test failed!"; exit 1; }
|
|
|
|
echo ""
|
|
echo "=== Step 6: Fixing SSLH Configuration ==="
|
|
# Remove the problematic /etc/default/sslh
|
|
rm -f /etc/default/sslh
|
|
echo "Removed /etc/default/sslh"
|
|
|
|
# Create systemd override
|
|
mkdir -p /etc/systemd/system/sslh.service.d
|
|
cat > /tmp/sslh-override.conf <<'EOF'
|
|
[Service]
|
|
EnvironmentFile=
|
|
ExecStart=
|
|
ExecStart=/usr/sbin/sslh --foreground -F /etc/sslh.cfg
|
|
EOF
|
|
|
|
mv /tmp/sslh-override.conf /etc/systemd/system/sslh.service.d/override.conf
|
|
chmod 644 /etc/systemd/system/sslh.service.d/override.conf
|
|
echo "Created SSLH systemd override"
|
|
|
|
# Reload systemd
|
|
systemctl daemon-reload
|
|
echo "Reloaded systemd"
|
|
|
|
echo ""
|
|
echo "=== Step 7: Restarting Services ==="
|
|
systemctl restart nginx
|
|
sleep 2
|
|
|
|
# Verify nginx is listening on 8444
|
|
for i in 1 2 3 4 5; do
|
|
if ss -tlnp | grep -q ':8444 '; then
|
|
echo "Nginx is listening on port 8444"
|
|
break
|
|
fi
|
|
echo "Waiting for nginx to listen on 8444... (attempt $i/5)"
|
|
sleep 2
|
|
if [ $i -eq 5 ]; then
|
|
echo "ERROR: Nginx failed to listen on port 8444!"
|
|
systemctl status nginx --no-pager || true
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Restart SSLH
|
|
systemctl stop sslh 2>/dev/null || true
|
|
pkill -9 sslh sslh-select 2>/dev/null || true
|
|
ss -tlnp | grep -q ':443 ' && fuser -k 443/tcp 2>/dev/null || true
|
|
sleep 2
|
|
systemctl enable sslh
|
|
systemctl restart sslh
|
|
sleep 3
|
|
|
|
if systemctl is-active --quiet sslh; then
|
|
echo "SSLH service is running"
|
|
if ss -tlnp | grep -q ':443 '; then
|
|
echo "SSLH is listening on port 443"
|
|
else
|
|
echo "WARNING: SSLH is running but not listening on port 443"
|
|
fi
|
|
else
|
|
echo "ERROR: SSLH service failed to start!"
|
|
systemctl status sslh --no-pager || true
|
|
journalctl -u sslh -n 20 --no-pager || true
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Step 8: Verifying Services ==="
|
|
echo "Listening ports:"
|
|
ss -tlnp | grep -E ':(22|80|443|8444|445) ' || true
|
|
|
|
echo ""
|
|
echo "=== Step 9: Testing Connectivity ==="
|
|
if timeout 2 bash -c '</dev/tcp/127.0.0.1/8444' 2>/dev/null; then
|
|
echo "SUCCESS: Nginx is accessible on port 8444"
|
|
else
|
|
echo "ERROR: Nginx is not accessible on port 8444"
|
|
fi
|
|
|
|
if ss -tlnp | grep -q ':443 '; then
|
|
echo "SUCCESS: SSLH is listening on port 443"
|
|
else
|
|
echo "ERROR: SSLH is not listening on port 443"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Step 10: Testing HTTP and HTTPS ==="
|
|
echo "Testing HTTP (port 80):"
|
|
HTTP_CONTENT=$(timeout 3 curl -s http://127.0.0.1:80/ 2>&1)
|
|
if echo "$HTTP_CONTENT" | grep -q "Demo app page"; then
|
|
echo "SUCCESS: HTTP serves demo page"
|
|
elif echo "$HTTP_CONTENT" | grep -qi "Welcome to nginx"; then
|
|
echo "ERROR: HTTP still serving default nginx page!"
|
|
echo "HTTP content preview:"
|
|
echo "$HTTP_CONTENT" | head -5
|
|
echo "Checking enabled sites..."
|
|
ls -la /etc/nginx/sites-enabled/
|
|
else
|
|
echo "WARNING: HTTP may not be serving demo page correctly"
|
|
echo "$HTTP_CONTENT" | head -5
|
|
fi
|
|
|
|
echo "Testing HTTPS (port 8444):"
|
|
HTTPS_CONTENT=$(timeout 3 curl -k -s https://127.0.0.1:8444/ 2>&1)
|
|
if echo "$HTTPS_CONTENT" | grep -q "Demo app page"; then
|
|
echo "SUCCESS: HTTPS serves demo page"
|
|
elif echo "$HTTPS_CONTENT" | grep -qi "Welcome to nginx"; then
|
|
echo "ERROR: HTTPS still serving default nginx page!"
|
|
echo "HTTPS content preview:"
|
|
echo "$HTTPS_CONTENT" | head -5
|
|
else
|
|
echo "WARNING: HTTPS may not be serving demo page correctly"
|
|
echo "$HTTPS_CONTENT" | head -5
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Step 11: Final Verification ==="
|
|
echo "Nginx enabled sites:"
|
|
ls -la /etc/nginx/sites-enabled/ || true
|
|
|
|
echo ""
|
|
echo "Nginx listening ports:"
|
|
ss -tlnp | grep nginx || true
|
|
|
|
echo ""
|
|
echo "SSLH status:"
|
|
systemctl is-active sslh && echo "SSLH: RUNNING" || echo "SSLH: NOT RUNNING"
|
|
|
|
echo ""
|
|
echo "=== Step 11: DNS Verification ==="
|
|
if [ -n "$DOMAIN" ]; then
|
|
echo "Verifying DNS resolution for $DOMAIN..."
|
|
if nslookup $DOMAIN >/dev/null 2>&1; then
|
|
RESOLVED_IP=$(nslookup $DOMAIN | grep -A 1 "Name:" | grep "Address:" | tail -1 | awk '{print $2}' || echo "")
|
|
if [ -n "$RESOLVED_IP" ]; then
|
|
echo " ✓ $DOMAIN resolves to $RESOLVED_IP"
|
|
else
|
|
echo " ✓ $DOMAIN resolves (IP not extracted)"
|
|
fi
|
|
else
|
|
echo " ✗ $DOMAIN does not resolve"
|
|
echo " This may indicate DNS records are not properly configured"
|
|
fi
|
|
|
|
# Test common subdomains
|
|
for subdomain in ssh smb; do
|
|
FQDN="$subdomain.$DOMAIN"
|
|
if nslookup $FQDN >/dev/null 2>&1; then
|
|
RESOLVED_IP=$(nslookup $FQDN | grep -A 1 "Name:" | grep "Address:" | tail -1 | awk '{print $2}' || echo "")
|
|
if [ -n "$RESOLVED_IP" ]; then
|
|
echo " ✓ $FQDN resolves to $RESOLVED_IP"
|
|
else
|
|
echo " ✓ $FQDN resolves"
|
|
fi
|
|
fi
|
|
done
|
|
else
|
|
echo "Skipping DNS verification (DOMAIN not set)"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Step 12: Let's Encrypt Certificate Generation ==="
|
|
if [ -n "$LETSENCRYPT_EMAIL" ] && [ -n "$DOMAIN" ]; then
|
|
echo "Domain: $DOMAIN"
|
|
echo "Email: $LETSENCRYPT_EMAIL"
|
|
echo "Checking for existing DNS records to determine subdomains..."
|
|
|
|
# Build domain list - start with root domain
|
|
DOMAINS="$DOMAIN"
|
|
|
|
# Check which subdomains have DNS records (indicating they're configured)
|
|
for subdomain in ssh smb ldap ldaps rdp mysql postgres redis mongo vnc ftp ftps smtp smtps imap imaps pop3 pop3s; do
|
|
if nslookup $subdomain.$DOMAIN >/dev/null 2>&1; then
|
|
DOMAINS="$DOMAINS $subdomain.$DOMAIN"
|
|
echo " Found: $subdomain.$DOMAIN"
|
|
fi
|
|
done
|
|
|
|
echo "Domains to include in certificate: $DOMAINS"
|
|
|
|
# Build certbot command with all domains
|
|
CERTBOT_CMD="certbot certonly --webroot -n --agree-tos -m '$LETSENCRYPT_EMAIL'"
|
|
for domain in $DOMAINS; do
|
|
CERTBOT_CMD="$CERTBOT_CMD -d $domain"
|
|
done
|
|
CERTBOT_CMD="$CERTBOT_CMD -w /var/www/html --keep-until-expiring"
|
|
|
|
echo "Running certbot..."
|
|
echo "Command: $CERTBOT_CMD"
|
|
sudo $CERTBOT_CMD 2>&1 | tee /tmp/certbot-output.log
|
|
CERTBOT_EXIT=$?
|
|
|
|
if [ $CERTBOT_EXIT -eq 0 ]; then
|
|
# Find certificate directory
|
|
CERT_DIR=$(sudo certbot certificates 2>/dev/null | grep -A 5 'Certificate Name:' | grep 'Certificate Path:' | head -1 | awk '{print $3}' | xargs dirname 2>/dev/null || echo '')
|
|
if [ -z "$CERT_DIR" ]; then
|
|
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
|
|
fi
|
|
|
|
if [ -f "$CERT_DIR/fullchain.pem" ] || [ -f "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" ]; then
|
|
CERT_PATH="$CERT_DIR/fullchain.pem"
|
|
KEY_PATH="$CERT_DIR/privkey.pem"
|
|
if [ ! -f "$CERT_PATH" ]; then
|
|
CERT_PATH="/etc/letsencrypt/live/$DOMAIN/fullchain.pem"
|
|
KEY_PATH="/etc/letsencrypt/live/$DOMAIN/privkey.pem"
|
|
fi
|
|
|
|
echo "Certificate found: $CERT_PATH"
|
|
echo "Updating nginx to use Let's Encrypt certificate..."
|
|
|
|
cat > /tmp/sslh-proxy-letsencrypt.conf <<EOF
|
|
server {
|
|
listen 127.0.0.1:8444 ssl http2 default_server;
|
|
server_name _;
|
|
ssl_certificate $CERT_PATH;
|
|
ssl_certificate_key $KEY_PATH;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
root /var/www/demo;
|
|
index index.html;
|
|
location / {
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
}
|
|
EOF
|
|
mv /tmp/sslh-proxy-letsencrypt.conf /etc/nginx/sites-available/sslh-proxy
|
|
chmod 644 /etc/nginx/sites-available/sslh-proxy
|
|
chmod 644 "$CERT_PATH" 2>/dev/null || true
|
|
chmod 640 "$KEY_PATH" 2>/dev/null || true
|
|
chown root:root "$CERT_PATH" "$KEY_PATH" 2>/dev/null || true
|
|
nginx -t && systemctl reload nginx && echo "SUCCESS: Nginx updated to use Let's Encrypt certificate" || systemctl restart nginx
|
|
echo "Certificate Subject Alternative Names:"
|
|
openssl x509 -in "$CERT_PATH" -noout -text 2>/dev/null | grep -A 1 'Subject Alternative Name' || true
|
|
else
|
|
echo "ERROR: Certificate file not found after certbot success"
|
|
echo "Checking certbot certificates:"
|
|
sudo certbot certificates 2>&1 | head -20
|
|
fi
|
|
else
|
|
echo "WARNING: Certbot failed (exit code: $CERTBOT_EXIT)"
|
|
echo "Certbot output (last 20 lines):"
|
|
cat /tmp/certbot-output.log 2>/dev/null | tail -20
|
|
echo "Continuing with self-signed certificate..."
|
|
fi
|
|
else
|
|
echo "Skipping Let's Encrypt (DOMAIN or LETSENCRYPT_EMAIL not set)"
|
|
echo "To enable: Run './sslh-lab fix --letsencrypt-email your@email.com' or set up during initial deployment"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Certificate in use:"
|
|
grep -E 'ssl_certificate|ssl_certificate_key' /etc/nginx/sites-available/sslh-proxy 2>/dev/null || echo "No SSL directives found"
|
|
|
|
echo ""
|
|
echo "=== Step 13: Final Verification ==="
|
|
echo "Nginx enabled sites:"
|
|
ls -la /etc/nginx/sites-enabled/ || true
|
|
|
|
echo ""
|
|
echo "Nginx listening ports:"
|
|
ss -tlnp | grep nginx || true
|
|
|
|
echo ""
|
|
echo "SSLH status:"
|
|
systemctl is-active sslh && echo "SSLH: RUNNING" || echo "SSLH: NOT RUNNING"
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "Fix Complete"
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "If HTTPS still doesn't work externally, check:"
|
|
echo "1. DNS is pointing to this server"
|
|
echo "2. Firewall allows port 443"
|
|
echo "3. SSLH is listening on port 443 (check above)"
|
|
echo ""
|