Během hovoru s technickou podporou Odoriku padl návrh, abych svůj problém s telefonem zkusil popsat zde na fóru. Jednak proto, abych mohl podat víc přesnějších informací o co vlastně jde, a za druhé aby tato diskuze mohla sloužit jako jakýsi "návod" pro případné další majitele telefonů stejné generace. Předně říkám, že nejsem odborník, spíše nadšený amatér. Mám tedy jakousi představu a nějaké základní znalosti, ale spoustu věcí si možná představuji zjednodušeně nebo si je domýšlím.
Téma se týká IP telefonů Cisco z "nové" řady využívající XML konfiguraci a firmware postavený na Javě. Konkrétně se jedná o populární modely 7961/41, ale také např. 7970 nebo levnější jednolinkové 7911/06. Tyto mám vyzkoušené, ale předpokládám že i ostatní z aktuální rodiny "Cisco Unified IP Phone" se budou chovat úplně stejně.
Jádrem problému je následující: Telefon SIP požadavky o registraci zasílá z náhodně generovaných portů, odpověď však očekává na jiném, pevně definovaném portu (typicky 5060). Jedná se o známé chování, pro úplnost přikládám citaci ze stránky Asterisk phone cisco 79x1 xml configuration files for SIP na Voip-Info.org:
Netuším, co Cisco k této implementaci vedlo, ale zkrátka je to tak a nelze s tím nic dělat - chování je pevně definované ve firmwaru a uživatel může změnit pouze onen konkrétní port, na kterém zařízení naslouchá.Note that as of version 8.0(2)SR1 the phone sends UDP SIP requests from a high source port. This means that it will send from (for example) source port 50116 to SIP port 5060 on the SIP server. This is acceptable behaviour as per the SIP RFC, but it is different to the Cisco ATA and 7940 SIP software (and many but not all phones) and may have ramifications on your firewall rules if you are expecting the phone to send packets out from source port 5060 as well (as you may have with 7940 and ATAs etc). There are a few phones around which behave in the same way although most don't - this is not a cisco specific behaviour and is NOT a bug.
Pro reálné použití to však má velmi nepříjemné důsledky. Běžný uživatel se totiž k ústředně připojuje přes NAT na svém domácím routeru (a obecně takových NATů může být na cestě mezi telefonem a ústřednou v podstatě libovolný počet). Když dojde k překladu adres, NAT může, ale také nemusí zachovat zdrojový port, ze kterého telefon SIP požadavek odeslal. To znamená, že aby odpověď ústředny prošla zpět napůl otevřenými vrátky NATu, musí být adresována zpět na tento náhodný port, ze kterého telefon resp. NAT požadavek odeslal. Taková odpověď úspěšně projde NATem zpátky až k telefonu ... a ten ji zahodí, protože ji očekával na portu 5060.
Zde přikládám několik screenshotů z Wiresharku, které demonstrují výše popsané chování:
V popisu prvního screenshotu jsem zmínil, že ačkoliv telefon UDP pakety zasílá z náhodného portu, na úrovni SIPu ústředně sděluje, že požadavek byl "Sent-by port: 5060". Zde se dostávám do roviny spekulací, avšak působí to na mě jako potvrzení výše uvedené anglické citace, že chování není tak úplně výmysl Cisco, ale má nějaký základ v SIP RFC.
Toto totiž souvisí i s vlastnostmi ústředny Asterisk. Bylo mi sice řečeno, že Odorik na Asterisku neběží, pro demonstraci však budu dále mluvit o Asterisku, protože jej znám. V nastavení sip.conf, kde jsou definovány jednotlivé pobočky lze totiž každé určit nastavení NATu. Pokud je definováno "nat=yes", Asterisk se chová "logicky" dle zákonitostí sítí - z jakého portu mi požadavky o registraci přišly, na takový port odpovídám. To proto, aby komunikace úspěšně prošla případnými NATy po cestě, které mohly zdrojový port libovolně měnit. Pokud však nastavíme "nat=no", Asterisk začně brát v úvahu obsah SIP hlavičky - odpovědi zasílám na takový port, který si zařízení SIP požadavkem vyžádalo.
Výše uvedené má za následek, že Cisco telefony 79x1 fungují naprosto bez problému, pokud je ústředna Asterisk ve stejné lokální síti a v nastavení poboček je uvedeno "nat=no". Toto mám ověřeno.
Takže jsme se konečně dostali k základní otázce - jak na základě výše uvedených znalostí zprovoznit Cisco telefony 79x1 v Internetu, resp. s Odorikem?
Momentálně mě napadají dvě možná řešení. První mi přijde o něco elegantnější, ale není použitelné vždy. Za předpokladu, že mezi telefonem a ústřednou je pouze jeden NAT - na domácím routeru uživatele, mělo by fungovat následující:
- Na ústředně nastavíme NAT=no, aby odpovědi zasílala ne zpět na port odkud požadavek přišel, ale ne port specifikovaný v SIP hlavičce.
- Na domácím routeru otevřeme port 5060 a nastavíme klasický port forwarding na IP adresu telefonu.
Druhé řešení, opět pouze teoretické:
- Na ústředně se nic nemění, odpověď je stále zasílána na stejný port, odkud přišel požadavek
- Na posledním NATu před telefonem vytvoříme pravidlo, které zajistí, že všechny odpovědi od ústředny budou adresovány na port 5060
No a zde bych tedy prosil o vyjádření ze strany Odoriku a případné komentáře uživatelů. Zejména by mě zajímalo, zda existuje reálná šance aplikovat 1. navržené řešení a zda by podle vás bylo funkční. Případně bych potřeboval poradit, jak by mělo vypadat pravidlo pro iptables vyžadované 2. navrženým řešením - už jsem nad tím strávil nějakou dobu, ale zatím se mi funkční zápis (který by fungoval na mém routeru) nedaří vymyslet.
A také děkuji za trpělivost všem, kteří dočetli až do konce