Давно я так не грався.

Дано:

  • PBX з одним інтерфейсом і двома білими IP-адресами на ньому: 10.0.0.1 як primary і 10.0.0.2 як secondary (сірі адреси я взяв для прикладу);
  • SIP-провайдер, який дає два різні транки на дві різні IP-адреси PBX із двома різними обліковими записами, але при цьому адреса піра з боку провайдера SIP-транка однакова для обох транків і також біла: 192.168.0.1;
  • велике бажання різні облікові записи SIP-транків пускати через окремі адреси PBX, бо у провайдера таке security.

Якщо викинути зайвий інформаційний шум із ввідних даних, то виявляється, що ми хочемо, щоб один локальний процес (Asterisk) під’єднувався до 192.168.0.1:5060 через 10.0.0.1 і 10.0.0.2 залежно від того, який обліковий запис використовується.

Тобто, нам потрібен статичний L7-маршрут (!!!).

Звісно, ніякий ip route/ip rule так ніколи не зробить. Голий iptables — також. Але є одне але.

Ми можемо обхитрити систему і сказати, що для другого облікового запису SIP-транка Asterisk у якості host має використовувати не 192.168.0.1, а, наприклад, 172.16.0.1, і цього разу це має бути будь-яка сіра IP-адреса. А далі вступає в дію махінація з DNAT/SNAT:

*nat
…
-A OUTPUT -d 172.16.0.1/32 -j MARK --set-xmark 0x10/0xffffffff
-A OUTPUT -d 172.16.0.1/32 -j DNAT --to-destination 192.168.0.1
-A POSTROUTING -m mark --mark 0x10 -j SNAT --to-source 10.0.0.2
…

Тут відбувається таке:

  1. трафік, який іде на фейкову IP-адресу, маркується якоюсь міткою (число взяте зі стелі, як, власне, і сіра IP-адреса);
  2. потім у цих же пакетах підміняється адреса призначення на адресу піра SIP-транка;
  3. потім за встановленою раніше міткою підміняється адреса відправника так, щоб трафік ішов від імені secondary IP.

Таким чином, увесь трафік, який іде на 172.16.0.1, насправді йде на 192.168.0.1, причому від імені 10.0.0.2.

Вуаля — все працює. Без додаткових інтерфейсів, ip route/ip rule, tc (навіть tc уміє NAT, виявляється) тощо.

Якщо ваш сервачок з Астеріском сидить за лінуксовим NAT’ом, а на самому маршрутизаторі треба переключатися між основним каналом і резервним (з різними зовнішніми IP-адресами), не забудьте давати команду

sudo conntrack -F

щоб клятий Астеріск не повісив SIP-транки з написом «Request sent».