Fix TLS cert (add SANs) and enhance logging for registration debugging
Phones were not registering with zero log entries — two root causes: 1. Self-signed cert lacked Subject Alternative Names (SANs). Modern TLS clients (iOS/Android SIP apps) require SANs and ignore CN-only certs, causing silent TLS handshake rejection. Cert generation now includes SANs (DNS + IP), and existing certs without SANs are auto-regenerated. 2. Logger only captured notice/warning/error — TLS handshake failures are logged at the security level. Added security to console logging. Also added: - Startup check verifying port 5061 is actually bound - TLS/cert diagnostics in vpn-diagnostics (SAN check, port check, self-signed warning with guidance for phone configuration) https://claude.ai/code/session_01Vm6NLaQuzM4VosAotqS1q8
This commit is contained in:
+41
-6
@@ -75,16 +75,27 @@ if [[ "$raw_cidr" =~ \.([0-9]+)/([0-9]+)$ ]]; then
|
|||||||
default_cidr="${raw_cidr%.*}.0/${BASH_REMATCH[2]}"
|
default_cidr="${raw_cidr%.*}.0/${BASH_REMATCH[2]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 5. Generate self-signed certs if missing ──────────────────
|
# ── 5. Generate self-signed certs ──────────────────────────────
|
||||||
|
# Regenerate if missing OR if existing cert lacks SANs (modern TLS clients require them)
|
||||||
|
regen_cert=false
|
||||||
if [[ ! -f /etc/asterisk/certs/server.crt ]]; then
|
if [[ ! -f /etc/asterisk/certs/server.crt ]]; then
|
||||||
|
regen_cert=true
|
||||||
|
elif ! openssl x509 -in /etc/asterisk/certs/server.crt -noout -ext subjectAltName 2>/dev/null | grep -q "DNS:"; then
|
||||||
|
log_info "Existing TLS cert lacks SANs — regenerating for mobile phone compatibility"
|
||||||
|
regen_cert=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $regen_cert; then
|
||||||
log_info "Generating self-signed TLS certificate..."
|
log_info "Generating self-signed TLS certificate..."
|
||||||
mkdir -p /etc/asterisk/certs
|
mkdir -p /etc/asterisk/certs
|
||||||
# Use DOMAIN_NAME as CN if available
|
|
||||||
cn="${DOMAIN_NAME:-asterisk-local}"
|
cn="${DOMAIN_NAME:-asterisk-local}"
|
||||||
|
# Include Subject Alternative Names — required by modern TLS clients (iOS/Android SIP apps)
|
||||||
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
|
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
|
||||||
-keyout /etc/asterisk/certs/server.key \
|
-keyout /etc/asterisk/certs/server.key \
|
||||||
-out /etc/asterisk/certs/server.crt \
|
-out /etc/asterisk/certs/server.crt \
|
||||||
-subj "/CN=${cn}" 2>/dev/null
|
-subj "/CN=${cn}" \
|
||||||
|
-addext "subjectAltName=DNS:${cn}${PUBLIC_IP:+,IP:${PUBLIC_IP}}" \
|
||||||
|
2>/dev/null
|
||||||
chown asterisk:asterisk /etc/asterisk/certs/server.*
|
chown asterisk:asterisk /etc/asterisk/certs/server.*
|
||||||
chmod 644 /etc/asterisk/certs/server.crt
|
chmod 644 /etc/asterisk/certs/server.crt
|
||||||
chmod 600 /etc/asterisk/certs/server.key
|
chmod 600 /etc/asterisk/certs/server.key
|
||||||
@@ -287,13 +298,13 @@ rungroup = asterisk
|
|||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f /etc/asterisk/logger.conf ]]; then
|
# ── logger.conf (always regenerated - ensures security logging is on) ──
|
||||||
cat > /etc/asterisk/logger.conf << 'EOF'
|
cat > /etc/asterisk/logger.conf << 'EOF'
|
||||||
[general]
|
[general]
|
||||||
[logfiles]
|
[logfiles]
|
||||||
console => notice,warning,error
|
; security level captures TLS handshake failures and auth issues
|
||||||
|
console => notice,warning,error,security
|
||||||
EOF
|
EOF
|
||||||
fi
|
|
||||||
|
|
||||||
# ── modules.conf (always regenerated - ensures chan_sip stays disabled) ──
|
# ── modules.conf (always regenerated - ensures chan_sip stays disabled) ──
|
||||||
cat > /etc/asterisk/modules.conf << 'EOF'
|
cat > /etc/asterisk/modules.conf << 'EOF'
|
||||||
@@ -368,6 +379,24 @@ for i in $(seq 1 60); do
|
|||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Verify PJSIP transports are listening
|
||||||
|
tls_ok=false
|
||||||
|
udp_ok=false
|
||||||
|
if asterisk -rx "pjsip show transports" 2>/dev/null | grep -q "transport-tls"; then
|
||||||
|
tls_ok=true
|
||||||
|
fi
|
||||||
|
if asterisk -rx "pjsip show transports" 2>/dev/null | grep -q "transport-udp"; then
|
||||||
|
udp_ok=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if port 5061 is actually bound
|
||||||
|
tls_listen=""
|
||||||
|
if command -v ss &>/dev/null; then
|
||||||
|
tls_listen=$(ss -tlnp 2>/dev/null | grep ":5061 " || true)
|
||||||
|
elif command -v netstat &>/dev/null; then
|
||||||
|
tls_listen=$(netstat -tlnp 2>/dev/null | grep ":5061 " || true)
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}"
|
echo -e "${CYAN}══════════════════════════════════════════════════════════════${NC}"
|
||||||
echo -e "${CYAN} Easy Asterisk (Docker)${NC}"
|
echo -e "${CYAN} Easy Asterisk (Docker)${NC}"
|
||||||
@@ -375,7 +404,13 @@ echo -e "${CYAN}═════════════════════
|
|||||||
echo -e " FQDN: ${GREEN}${DOMAIN_NAME:-not set}${NC}"
|
echo -e " FQDN: ${GREEN}${DOMAIN_NAME:-not set}${NC}"
|
||||||
echo -e " Public IP: ${GREEN}${PUBLIC_IP:-unknown}${NC}"
|
echo -e " Public IP: ${GREEN}${PUBLIC_IP:-unknown}${NC}"
|
||||||
echo -e " TURN/STUN: ${GREEN}${turn_server}${NC}"
|
echo -e " TURN/STUN: ${GREEN}${turn_server}${NC}"
|
||||||
|
if $tls_ok && [[ -n "$tls_listen" ]]; then
|
||||||
echo -e " TLS: ${GREEN}Enabled (port 5061)${NC}"
|
echo -e " TLS: ${GREEN}Enabled (port 5061)${NC}"
|
||||||
|
elif $tls_ok; then
|
||||||
|
echo -e " TLS: ${YELLOW}Transport loaded but port 5061 not bound — check certs${NC}"
|
||||||
|
else
|
||||||
|
echo -e " TLS: ${RED}NOT LOADED — check Asterisk logs${NC}"
|
||||||
|
fi
|
||||||
echo -e " ICE: ${GREEN}Enabled${NC}"
|
echo -e " ICE: ${GREEN}Enabled${NC}"
|
||||||
echo -e "${CYAN}──────────────────────────────────────────────────────────────${NC}"
|
echo -e "${CYAN}──────────────────────────────────────────────────────────────${NC}"
|
||||||
echo -e " SIP clients connect to: ${GREEN}${DOMAIN_NAME:-$local_ip}:5061${NC} (TLS)"
|
echo -e " SIP clients connect to: ${GREEN}${DOMAIN_NAME:-$local_ip}:5061${NC} (TLS)"
|
||||||
|
|||||||
@@ -127,6 +127,66 @@ else
|
|||||||
fail "pjsip.conf not found"
|
fail "pjsip.conf not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── Test 2b: TLS Certificate & Port Checks ────────────────────
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}2b. TLS / Certificate Status${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if port 5061 is actually listening
|
||||||
|
if command -v ss &>/dev/null; then
|
||||||
|
tls_listen=$(ss -tlnp 2>/dev/null | grep ":5061 " || true)
|
||||||
|
elif command -v netstat &>/dev/null; then
|
||||||
|
tls_listen=$(netstat -tlnp 2>/dev/null | grep ":5061 " || true)
|
||||||
|
else
|
||||||
|
tls_listen=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$tls_listen" ]]; then
|
||||||
|
pass "Port 5061 (TLS) is listening"
|
||||||
|
else
|
||||||
|
fail "Port 5061 (TLS) is NOT listening"
|
||||||
|
warn "Asterisk TLS transport failed to start — check certs and logs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check TLS cert
|
||||||
|
cert_file="/etc/asterisk/certs/server.crt"
|
||||||
|
if [[ -f "$cert_file" ]]; then
|
||||||
|
pass "TLS certificate exists: $cert_file"
|
||||||
|
|
||||||
|
# Check cert CN/SAN
|
||||||
|
cert_cn=$(openssl x509 -in "$cert_file" -noout -subject 2>/dev/null | sed 's/.*CN *= *//')
|
||||||
|
cert_san=$(openssl x509 -in "$cert_file" -noout -ext subjectAltName 2>/dev/null | grep -oP 'DNS:\K[^,]+' || true)
|
||||||
|
cert_expiry=$(openssl x509 -in "$cert_file" -noout -enddate 2>/dev/null | cut -d= -f2)
|
||||||
|
|
||||||
|
info "Cert CN: ${cert_cn:-unknown}"
|
||||||
|
if [[ -n "$cert_san" ]]; then
|
||||||
|
pass "Cert has SAN (Subject Alt Name): ${cert_san}"
|
||||||
|
else
|
||||||
|
fail "Cert has NO SAN — modern phones (iOS/Android) will reject it"
|
||||||
|
warn "Delete /etc/asterisk/certs/server.crt and restart to regenerate with SANs"
|
||||||
|
fi
|
||||||
|
info "Cert expires: ${cert_expiry:-unknown}"
|
||||||
|
|
||||||
|
# Check if cert is self-signed
|
||||||
|
issuer=$(openssl x509 -in "$cert_file" -noout -issuer 2>/dev/null | sed 's/.*CN *= *//')
|
||||||
|
if [[ "$issuer" == "$cert_cn" ]]; then
|
||||||
|
warn "Cert is SELF-SIGNED — phones must be set to accept self-signed certs"
|
||||||
|
info "In your SIP app: disable TLS certificate verification / allow self-signed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify PJSIP transport loaded it
|
||||||
|
if command -v asterisk &>/dev/null; then
|
||||||
|
transport_status=$(asterisk -rx "pjsip show transports" 2>/dev/null || true)
|
||||||
|
if echo "$transport_status" | grep -q "transport-tls"; then
|
||||||
|
pass "PJSIP TLS transport is loaded"
|
||||||
|
else
|
||||||
|
fail "PJSIP TLS transport NOT loaded — cert may be invalid"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fail "TLS certificate not found at $cert_file"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Test 3: Check RTP and ICE/STUN configuration ─────────────
|
# ── Test 3: Check RTP and ICE/STUN configuration ─────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}3. RTP / ICE / STUN Configuration${NC}"
|
echo -e "${BOLD}3. RTP / ICE / STUN Configuration${NC}"
|
||||||
|
|||||||
Reference in New Issue
Block a user