Fix 27s call ringing delay: TURN credential mismatch and STUN DNS TTL=0
Two bugs caused ICE candidate gathering to fail and timeout (~27 seconds)
before falling back to direct media on every call:
1. TURN credential mismatch — when TURN_PASSWORD was empty in .env,
coturn defaulted to "changeme" but the entrypoint auto-generated a
different random password for Asterisk. Every TURN auth attempt failed
("check_stun_auth: user easyasterisk credentials are incorrect").
2. STUN DNS TTL=0 — using the FQDN as stunaddr caused DNS resolution
that returned TTL=0, making Asterisk cancel recurring STUN resolution
entirely. Since coturn runs on the same host (network_mode: host),
rtp.conf now uses 127.0.0.1 which needs no DNS at all.
Also documents the Android Call Integration audio issue (ConnectionService
routes audio through the native telephony path, breaking VoIP RTP).
https://claude.ai/code/session_01KWVtEt9MmZdywcu7WmgchX
This commit is contained in:
+2
-2
@@ -60,8 +60,8 @@ VLAN_SUBNETS=
|
|||||||
|
|
||||||
# ── TURN/STUN Settings ──────────────────────────────────────
|
# ── TURN/STUN Settings ──────────────────────────────────────
|
||||||
# Used by coturn for TURN relay authentication.
|
# Used by coturn for TURN relay authentication.
|
||||||
# If TURN_PASSWORD is empty, a random password is generated on
|
# Both coturn and Asterisk must use the SAME password.
|
||||||
# first startup and saved to /etc/easy-asterisk/config.
|
# If empty, both default to "changeme" — set a real password here.
|
||||||
#
|
#
|
||||||
# These credentials are shared between coturn and Asterisk.
|
# These credentials are shared between coturn and Asterisk.
|
||||||
# SIP clients do NOT need these - only the server uses them.
|
# SIP clients do NOT need these - only the server uses them.
|
||||||
|
|||||||
@@ -663,6 +663,22 @@ For **any SIP app**:
|
|||||||
- FQDN mode enables ICE (Interactive Connectivity Establishment) which handles network changes better
|
- FQDN mode enables ICE (Interactive Connectivity Establishment) which handles network changes better
|
||||||
- Alternatively, keep your phone on one network type (WiFi or mobile data) during calls
|
- Alternatively, keep your phone on one network type (WiFi or mobile data) during calls
|
||||||
|
|
||||||
|
### "No audio when Call Integration is enabled" (Android)
|
||||||
|
|
||||||
|
Some Android SIP apps (Sipnetic, Olinuxino, etc.) offer a "Call Integration" feature that routes calls through Android's native dialer (ConnectionService API). When enabled:
|
||||||
|
|
||||||
|
- Incoming calls appear in the native phone app
|
||||||
|
- The headset media button works for answering
|
||||||
|
- **But the caller may get no audio**
|
||||||
|
|
||||||
|
**Why this happens:**
|
||||||
|
Android's ConnectionService routes audio through the native telephony audio path, which doesn't always relay VoIP RTP audio correctly. This is a client-side Android issue, not an Asterisk problem. It affects both stock Android and LineageOS.
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Disable "Call Integration" in your SIP app's settings
|
||||||
|
- Use the SIP app's own answer button instead of the headset media button
|
||||||
|
- If you need headset button support, check if your SIP app supports media button handling without Call Integration
|
||||||
|
|
||||||
### "My IP changed and FQDN stopped working"
|
### "My IP changed and FQDN stopped working"
|
||||||
|
|
||||||
See [Dynamic IP Handling](#dynamic-ip-handling) section. You need to set up DDNS.
|
See [Dynamic IP Handling](#dynamic-ip-handling) section. You need to set up DDNS.
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ services:
|
|||||||
- TURN_ENABLED=y
|
- TURN_ENABLED=y
|
||||||
- TURN_SERVER=${DOMAIN_NAME:?}:${TURN_PORT:-3478}
|
- TURN_SERVER=${DOMAIN_NAME:?}:${TURN_PORT:-3478}
|
||||||
- TURN_USERNAME=${TURN_USERNAME:-easyasterisk}
|
- TURN_USERNAME=${TURN_USERNAME:-easyasterisk}
|
||||||
- TURN_PASSWORD=${TURN_PASSWORD:-}
|
- TURN_PASSWORD=${TURN_PASSWORD:-changeme}
|
||||||
|
|
||||||
# ── RTP Port Range ──
|
# ── RTP Port Range ──
|
||||||
- RTP_START=${RTP_START:-10000}
|
- RTP_START=${RTP_START:-10000}
|
||||||
|
|||||||
+17
-13
@@ -54,17 +54,15 @@ else
|
|||||||
log_warn "Could not detect public IP. Set PUBLIC_IP in .env"
|
log_warn "Could not detect public IP. Set PUBLIC_IP in .env"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 3. Generate TURN password if not provided ─────────────────
|
# ── 3. TURN credentials ─────────────────────────────────────────
|
||||||
|
# The password MUST match what coturn was started with. In Docker, both
|
||||||
|
# read from the same env-var / .env file, so we use the value as-is.
|
||||||
|
# Auto-generating a different password here would create a mismatch
|
||||||
|
# (coturn is already running with ITS copy of the env-var).
|
||||||
TURN_USERNAME="${TURN_USERNAME:-easyasterisk}"
|
TURN_USERNAME="${TURN_USERNAME:-easyasterisk}"
|
||||||
if [[ -z "${TURN_PASSWORD:-}" ]] || [[ "${TURN_PASSWORD}" == "changeme" ]]; then
|
TURN_PASSWORD="${TURN_PASSWORD:-changeme}"
|
||||||
# Check if we already generated one previously
|
if [[ "${TURN_PASSWORD}" == "changeme" ]]; then
|
||||||
if [[ -f "$CONFIG_FILE" ]] && grep -q "^TURN_PASSWORD=" "$CONFIG_FILE"; then
|
log_warn "TURN password is the default 'changeme' — set TURN_PASSWORD in .env for better security"
|
||||||
TURN_PASSWORD=$(grep "^TURN_PASSWORD=" "$CONFIG_FILE" | cut -d'"' -f2)
|
|
||||||
fi
|
|
||||||
if [[ -z "${TURN_PASSWORD:-}" ]] || [[ "${TURN_PASSWORD}" == "changeme" ]]; then
|
|
||||||
TURN_PASSWORD=$(gen_password)
|
|
||||||
log_info "Generated TURN password (saved to config)"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 4. Detect local network ──────────────────────────────────
|
# ── 4. Detect local network ──────────────────────────────────
|
||||||
@@ -282,15 +280,21 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# ── rtp.conf (always regenerated - includes TURN credentials) ──
|
# ── rtp.conf (always regenerated - includes TURN credentials) ──
|
||||||
log_info "Configuring RTP with ICE + STUN + TURN..."
|
# Use 127.0.0.1 for stunaddr/turnaddr because coturn runs on the same host
|
||||||
|
# (network_mode: host). Using the FQDN would cause DNS resolution, and if the
|
||||||
|
# DNS TTL is 0 Asterisk cancels recurring resolution — breaking ICE entirely
|
||||||
|
# and adding a ~27-second timeout delay to every call.
|
||||||
|
turn_port="${turn_server##*:}"
|
||||||
|
local_turn="127.0.0.1:${turn_port:-3478}"
|
||||||
|
log_info "Configuring RTP with ICE + STUN + TURN (local: ${local_turn})..."
|
||||||
cat > /etc/asterisk/rtp.conf << EOF
|
cat > /etc/asterisk/rtp.conf << EOF
|
||||||
[general]
|
[general]
|
||||||
rtpstart=${RTP_START:-10000}
|
rtpstart=${RTP_START:-10000}
|
||||||
rtpend=${RTP_END:-20000}
|
rtpend=${RTP_END:-20000}
|
||||||
strictrtp=yes
|
strictrtp=yes
|
||||||
icesupport=yes
|
icesupport=yes
|
||||||
stunaddr=${turn_server}
|
stunaddr=${local_turn}
|
||||||
turnaddr=${turn_server}
|
turnaddr=${local_turn}
|
||||||
turnusername=${TURN_USERNAME}
|
turnusername=${TURN_USERNAME}
|
||||||
turnpassword=${TURN_PASSWORD}
|
turnpassword=${TURN_PASSWORD}
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
Reference in New Issue
Block a user