Why this is useful
With some TIM VoIP setups the Outbound Proxy is provided as a hostname (e.g. d835s1.co.imsw.telecomitalia.it).
Some devices/firmware (FRITZ!Box, Grandstream, ATA gateways, “open” VoIP routers, etc.) may fail when you enter that hostname, but work if you enter the IP address instead.
The idea:
- query the SRV record
_sip._udp.<outbound> - pick the preferred target (lowest priority)
- resolve the target to an A record (IPv4) → that IP is what you enter as outbound proxy
Common symptoms
- SIP registration fails only when outbound proxy is a hostname
- the same account works if you replace the outbound proxy with the resolved IP
- “DNS error / resolve failed / server unreachable” style errors
SRV quick note: Priority vs Weight
SRV records carry:
- Priority: lower = preferred
- Weight: load-balancing for targets with the same priority
The scripts below pick automatically: lowest Priority, then lowest Weight.
Automated solution (recommended)
Two scripts:
- Windows: PowerShell (tim_proxy_ip.ps1 )
- Linux (and also Windows): Python (tim_proxy_ip.py )
Both scripts:
- print an intro at startup
- ask for your TIM outbound proxy hostname
- do SRV → pick best record → resolve A → print the IP(s)
- also show the DNS servers configured on the system (and attempt to detect TIM via reverse DNS)
Windows (PowerShell)
Run
Open CMD or PowerShell in the folder where the script is and run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\tim_proxy_ip.ps1
The script will ask:
- your TIM outbound proxy hostname
- optionally, a specific DNS server to query
In section [3] you’ll get one or more IPs: those are the ones to enter as Outbound Proxy.

Code (tim_proxy_ip.ps1)
# tim_proxy_ip.ps1
$intro = @"
===============================================================================
TIM Outbound Proxy -> IP (SRV -> A)
===============================================================================
OBIETTIVO
Alcuni dispositivi (FRITZ!Box, Grandstream, ATA VoIP, router VoIP "liberi", ecc.)
possono avere problemi quando l'Outbound Proxy TIM viene inserito come hostname
(alfanumerico). In molti casi invece funziona correttamente se si inserisce
direttamente l'indirizzo IP.
COSA FA QUESTO SCRIPT
1) Interroga il DNS con una query SRV su:
_sip._udp.<tuo_outbound_proxy_TIM>
e ottiene i server reali (target) del servizio SIP.
2) Sceglie automaticamente il record SRV preferito:
Priority piu bassa, poi Weight piu basso
3) Risolve il target scelto con una query A per ottenere uno o piu IP (IPv4).
4) Mostra anche i DNS configurati sul PC e prova a riconoscere TIM via reverse DNS.
COME USARE IL RISULTATO
Gli IP stampati nella sezione [3] sono quelli da inserire come:
OUTBOUND PROXY / SIP OUTBOUND PROXY
sul tuo dispositivo (Fritz!Box, Grandstream, ATA, router, ecc.).
Se escono piu IP e il primo non va, prova gli altri.
===============================================================================
"@
Write-Host $intro
function Normalize-SrvName([string]$v) {
$v = $v.Trim().TrimEnd(".")
if ($v.ToLower().StartsWith("_sip._udp.")) { return $v }
if ($v.ToLower().StartsWith("sip.udp.")) { return "_sip._udp." + $v.Substring(8) }
return "_sip._udp." + $v
}
$outbound = Read-Host "Inserisci il tuo outbound proxy TIM (es: d835s1.co.imsw.telecomitalia.it)"
$srvName = Normalize-SrvName $outbound
$useDns = Read-Host "Vuoi interrogare un DNS specifico? (s/N)"
$dnsServer = $null
if ($useDns.ToLower().StartsWith("s")) {
$dnsServer = Read-Host "Inserisci IP del DNS (es: 85.37.17.51)"
}
Write-Host "`n[1] Query SRV: $srvName" -ForegroundColor Cyan
try {
$srv = if ($dnsServer) {
Resolve-DnsName -Type SRV -Name $srvName -Server $dnsServer -ErrorAction Stop
} else {
Resolve-DnsName -Type SRV -Name $srvName -ErrorAction Stop
}
} catch {
Write-Host "ERRORE: query SRV fallita. Dettaglio: $($_.Exception.Message)" -ForegroundColor Red
exit 2
}
$records = $srv | Where-Object { $_.QueryType -eq "SRV" } |
Select-Object NameTarget, Priority, Weight, Port
if (-not $records) {
Write-Host "Nessun record SRV trovato nell'output." -ForegroundColor Red
exit 3
}
Write-Host "`nRecord SRV trovati (ordinati per Priority poi Weight):" -ForegroundColor Cyan
$records | Sort-Object Priority, Weight, Port, NameTarget | Format-Table -AutoSize
$best = $records | Sort-Object Priority, Weight | Select-Object -First 1
$target = ($best.NameTarget).TrimEnd(".")
Write-Host "`n[2] Scelto automaticamente (Priority piu bassa, poi Weight): $target (port $($best.Port))" -ForegroundColor Cyan
Write-Host "`n[3] IP da inserire come OUTBOUND PROXY (Fritz!Box / Grandstream / altri):" -ForegroundColor Cyan
try {
$a = if ($dnsServer) {
Resolve-DnsName -Type A -Name $target -Server $dnsServer -ErrorAction Stop
} else {
Resolve-DnsName -Type A -Name $target -ErrorAction Stop
}
$ips = $a | Where-Object { $_.QueryType -eq "A" } | Select-Object -ExpandProperty IPAddress
$ips | ForEach-Object { " - $_" }
# riga pronta da copiare
if ($ips -and $ips.Count -gt 0) {
Write-Host "`nCopia/Incolla:" -ForegroundColor Yellow
Write-Host ("Outbound Proxy = {0}" -f $ips[0]) -ForegroundColor Yellow
}
} catch {
Write-Host "ERRORE: risoluzione A fallita. Dettaglio: $($_.Exception.Message)" -ForegroundColor Red
exit 4
}
Write-Host "`n[4] DNS configurati sul PC (IPv4):" -ForegroundColor Cyan
$localDns = @()
try {
$localDns = Get-DnsClientServerAddress -AddressFamily IPv4 |
Select-Object -ExpandProperty ServerAddresses -Unique
} catch {
$localDns = @()
}
if (-not $localDns -or $localDns.Count -eq 0) {
Write-Host " (non rilevati)"
} else {
foreach ($ip in $localDns) {
$rdns = $null
try {
$ptr = Resolve-DnsName -Type PTR -Name $ip -ErrorAction Stop
$rdns = ($ptr | Select-Object -First 1).NameHost
} catch { }
$tag = ""
if ($rdns) {
$low = $rdns.ToLower()
if ($low.Contains("telecomitalia") -or $low.Contains("tim") -or $low.Contains("alice")) {
$tag = " <-- sembra TIM (reverse DNS)"
}
Write-Host (" - {0} ({1}){2}" -f $ip, $rdns, $tag)
} else {
Write-Host (" - {0}" -f $ip)
}
}
}
Write-Host "`n[5] DNS TIM comuni (se vuoi provarli manualmente):" -ForegroundColor Cyan
Write-Host " - 85.37.17.51"
Write-Host " - 85.38.28.97"
Write-Host "`nFatto."
Linux (Debian/Ubuntu etc.) – Python
Requirements
python3- it helps to have
digornslookupinstalled (often from thednsutilspackage)
No root is required. If dig is available the script will use it, otherwise it falls back to nslookup.
Run
python3 tim_proxy_ip.py
Code (tim_proxy_ip.py)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import platform
import re
import socket
import subprocess
from dataclasses import dataclass
from typing import List, Optional
INTRO = r"""
===============================================================================
TIM Outbound Proxy -> IP (SRV -> A)
===============================================================================
OBIETTIVO
Alcuni dispositivi (FRITZ!Box, Grandstream, ATA VoIP, router VoIP "liberi", ecc.)
possono avere problemi quando l'Outbound Proxy TIM viene inserito come hostname
(alfanumerico). In molti casi invece funziona correttamente se si inserisce
direttamente l'indirizzo IP.
COSA FA QUESTO SCRIPT
1) Query SRV su:
_sip._udp.<tuo_outbound_proxy_TIM>
e ottiene i target reali del servizio SIP.
2) Sceglie automaticamente il record SRV preferito:
Priority piu bassa, poi Weight piu basso
3) Query A sul target scelto per ottenere uno o piu IP (IPv4).
4) Mostra anche i DNS configurati sul sistema (Linux/Windows) e prova a
riconoscere TIM via reverse DNS quando possibile.
COME USARE IL RISULTATO
Gli IP stampati nella sezione [3] sono quelli da inserire come:
OUTBOUND PROXY / SIP OUTBOUND PROXY
sul tuo dispositivo (Fritz!Box, Grandstream, ATA, router, ecc.).
Se escono piu IP e il primo non va, prova gli altri.
===============================================================================
"""
@dataclass
class SrvRecord:
priority: int
weight: int
port: int
target: str
def have_cmd(name: str) -> bool:
from shutil import which
return which(name) is not None
def run_cmd(cmd: List[str]) -> str:
p = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="ignore")
out = (p.stdout or "") + "\n" + (p.stderr or "")
return out.strip()
def normalize_srv_name(user_value: str) -> str:
v = user_value.strip().rstrip(".")
if v.lower().startswith("_sip._udp."):
return v
if v.lower().startswith("sip.udp."):
return "_sip._udp." + v[len("sip.udp."):]
return "_sip._udp." + v
def parse_srv_records(text: str) -> List[SrvRecord]:
records: List[SrvRecord] = []
# 1) DIG:
# _sip._udp.xxx. 36352 IN SRV 10 0 5060 target.
dig_pat = re.compile(
r"^\S+\s+\d+\s+\S+\s+SRV\s+(\d+)\s+(\d+)\s+(\d+)\s+([^\s]+)\.?\s*$",
flags=re.IGNORECASE | re.MULTILINE,
)
for m in dig_pat.finditer(text):
records.append(SrvRecord(
priority=int(m.group(1)),
weight=int(m.group(2)),
port=int(m.group(3)),
target=m.group(4).rstrip("."),
))
# 2) NSLOOKUP Linux:
# ... service = 10 0 5060 target.
ns_linux_pat = re.compile(
r"^\S+\s+service\s*=\s*(\d+)\s+(\d+)\s+(\d+)\s+([^\s]+)\.?\s*$",
flags=re.IGNORECASE | re.MULTILINE,
)
for m in ns_linux_pat.finditer(text):
records.append(SrvRecord(
priority=int(m.group(1)),
weight=int(m.group(2)),
port=int(m.group(3)),
target=m.group(4).rstrip("."),
))
# 3) NSLOOKUP Windows:
priority_terms = r"(?:priority|priorit[aà])"
weight_terms = r"(?:weight|peso)"
port_terms = r"(?:port|porta)"
target_terms = r"(?:svr hostname|server hostname|host(?:name)? del server|target)"
ns_win_pat = re.compile(
rf"{priority_terms}\s*=\s*(\d+).*?"
rf"{weight_terms}\s*=\s*(\d+).*?"
rf"{port_terms}\s*=\s*(\d+).*?"
rf"{target_terms}\s*=\s*([^\s]+)",
flags=re.IGNORECASE | re.DOTALL,
)
for m in ns_win_pat.finditer(text):
records.append(SrvRecord(
priority=int(m.group(1)),
weight=int(m.group(2)),
port=int(m.group(3)),
target=m.group(4).rstrip("."),
))
# Dedup stabile
seen = set()
out: List[SrvRecord] = []
for r in records:
key = (r.priority, r.weight, r.port, r.target)
if key not in seen:
seen.add(key)
out.append(r)
return out
def query_srv(name: str, dns_server: Optional[str]) -> str:
if have_cmd("dig"):
cmd = ["dig"]
if dns_server:
cmd.append(f"@{dns_server}")
cmd += ["+noall", "+answer", "SRV", name]
return run_cmd(cmd)
cmd = ["nslookup", "-type=SRV", name]
if dns_server:
cmd.append(dns_server)
return run_cmd(cmd)
def query_a(name: str, dns_server: Optional[str]) -> str:
if have_cmd("dig"):
cmd = ["dig"]
if dns_server:
cmd.append(f"@{dns_server}")
cmd += ["+short", "A", name]
return run_cmd(cmd)
cmd = ["nslookup", "-type=A", name]
if dns_server:
cmd.append(dns_server)
return run_cmd(cmd)
def parse_a_ipv4(text: str, dns_server: Optional[str]) -> List[str]:
ips = re.findall(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", text)
if dns_server:
ips = [ip for ip in ips if ip != dns_server]
seen, out = set(), []
for ip in ips:
if ip not in seen:
seen.add(ip)
out.append(ip)
return out
def reverse_dns(ip: str) -> Optional[str]:
try:
name, _, _ = socket.gethostbyaddr(ip)
return name.rstrip(".")
except Exception:
return None
def get_local_dns_servers_linux() -> List[str]:
dns: List[str] = []
try:
with open("/etc/resolv.conf", "r", encoding="utf-8", errors="ignore") as f:
for line in f:
line = line.strip()
if line.startswith("nameserver"):
parts = line.split()
if len(parts) >= 2 and re.match(r"^(?:\d{1,3}\.){3}\d{1,3}$", parts[1]):
dns.append(parts[1])
except Exception:
pass
seen, out = set(), []
for ip in dns:
if ip not in seen:
seen.add(ip)
out.append(ip)
return out
def get_local_dns_servers_windows() -> List[str]:
try:
ps_cmd = [
"powershell", "-NoProfile", "-Command",
"Get-DnsClientServerAddress -AddressFamily IPv4 | "
"Select-Object -ExpandProperty ServerAddresses | "
"Where-Object { $_ -match '^(\\d{1,3}\\.){3}\\d{1,3}$' }"
]
txt = run_cmd(ps_cmd)
lines = [x.strip() for x in txt.splitlines() if x.strip()]
seen, out = set(), []
for ip in lines:
if ip not in seen:
seen.add(ip)
out.append(ip)
return out
except Exception:
return []
def get_local_dns_servers() -> List[str]:
sysname = platform.system().lower()
if "windows" in sysname:
return get_local_dns_servers_windows()
return get_local_dns_servers_linux()
def is_ipv4(s: str) -> bool:
return bool(re.match(r"^(?:\d{1,3}\.){3}\d{1,3}$", s.strip()))
def main() -> None:
print(INTRO)
outbound = ""
while not outbound:
outbound = input("Inserisci il tuo outbound proxy TIM (es: d835s1.co.imsw.telecomitalia.it): ").strip()
srv_name = normalize_srv_name(outbound)
use_dns = input("Vuoi interrogare un DNS specifico? (s/N): ").strip().lower().startswith("s")
dns_server = None
if use_dns:
dns_server = ""
while not is_ipv4(dns_server):
dns_server = input("Inserisci IP del DNS (es: 85.37.17.51): ").strip()
print(f"\n[1] Query SRV: {srv_name}" + (f" (DNS: {dns_server})" if dns_server else " (DNS: sistema)"))
srv_txt = query_srv(srv_name, dns_server=dns_server)
records = parse_srv_records(srv_txt)
if not records:
print("\nERRORE: non ho trovato record SRV nell'output.")
print("\n--- Output (debug) ---\n")
print(srv_txt)
return
records_sorted = sorted(records, key=lambda r: (r.priority, r.weight, r.port, r.target))
print("\nRecord SRV trovati (ordinati per Priority poi Weight):")
for i, r in enumerate(records_sorted, 1):
print(f" {i:02d}) priority={r.priority} weight={r.weight} port={r.port} target={r.target}")
best = min(records, key=lambda r: (r.priority, r.weight))
target = best.target.rstrip(".")
print(f"\n[2] Scelto automaticamente (Priority piu bassa, poi Weight): {target} (port {best.port})")
print("\n[3] IP da inserire come OUTBOUND PROXY (Fritz!Box / Grandstream / altri):")
a_txt = query_a(target, dns_server=dns_server)
ips = parse_a_ipv4(a_txt, dns_server=dns_server)
if not ips and not dns_server:
try:
_, _, ip2 = socket.gethostbyname_ex(target)
ips = sorted(set(ip2))
except Exception:
ips = []
if not ips:
print(" (nessun IPv4 trovato)")
print("\n--- Output A (debug) ---\n")
print(a_txt)
return
for ip in ips:
print(f" - {ip}")
# riga pronta da copiare
print("\nCopia/Incolla:")
print(f"Outbound Proxy = {ips[0]}")
local_dns = get_local_dns_servers()
print("\n[4] DNS configurati sul sistema (IPv4):")
if not local_dns:
print(" (non rilevati)")
else:
for d in local_dns:
rdns = reverse_dns(d)
tag = ""
if rdns:
low = rdns.lower()
if ("telecomitalia" in low) or ("tim" in low) or ("alice" in low):
tag = " <-- sembra TIM (reverse DNS)"
print(f" - {d} ({rdns}){tag}")
else:
print(f" - {d}")
print("\n[5] DNS TIM comuni (se vuoi provarli manualmente):")
print(" - 85.37.17.51")
print(" - 85.38.28.97")
print("\nFatto.")
if __name__ == "__main__":
main()
Where to paste the resolved IP
Device UI labels differ, but you typically want:
- Outbound Proxy
- SIP Outbound Proxy
- sometimes Proxy Server (on certain ATA/router UIs)
Examples:
- FRITZ!Box: set the Outbound proxy field to the resolved IP
- Grandstream: set Outbound Proxy (or equivalent SIP settings)

Once configured correctly, the port status shows Registered:

If you see multiple IPs and the first one doesn’t work, try the others.
Troubleshooting
- DNS cache: on Windows you can run
ipconfig /flushdns. - Router DNS: your PC often uses the router as DNS (e.g.
192.168.1.1). That’s fine, but for testing you can query a TIM DNS directly. - IPs can change: TIM may change targets/IPs over time; just re-run the script and update your configuration.
- Transport/ports: this script only resolves the IP (A record). Keep the other SIP parameters you already have from TIM.
Disclaimer
Provided as-is. Use it only on your own line/contract and in compliance with your provider’s terms.
Use the share button below if you liked it.
Your click is my virtual high-five.