written on Wednesday, May 8, 2013
Крім того, що я катаюся на паромах-літаках і пишу криптоанархічний Voip, на мені ще висить трохи дурної роботи по підтримці чужих старих вебхостів.
Вебхости засунуті за nginx і особливого інтересу не представляють, але є одна деталь, яка називається "дефіцит IP4 адрес". Вебхости живуть на віртуальній машині, яка хоститься на селектелі, який ВНЕЗАПНО став чаржити по 70 дерев'яних на місяць за кожен виданий IP4 адрес. Мотивують.

Оскільки машина все одно засунута за реверс-проксі клаудфрайра і більше ні для чого, крім наливання трафіку з мережі клаудфлайра ця адреса не потрібна, народився хитрий план.

Від адреси відмовитися, оренду не платити, а клаудфлайровський проксі натравити одразу на IP6 адресу. Вобщемто план спрацював, але з деякими хаками.
Спочатку я влаштував генеральну репетицію. Налаштував клаудфларовську проксю гнати трафік на іншу IP4 адресу (сусідню віртуальну машину), а вже звідти гнати через IP6 на справжній бекенд. Нижче схема, де квадратними дужками позначені хости, а круглими — адреси/інтерфейси.
[code]
[CLIENT](IP4) -> (IP4)[CFLARE ](IP4) -> (IP4)[TESTBOX](IP6) -> (IP6)[WWW]
[/code]
Для цього на тестбоксі довелося оновити nginx до 1.3 і написати ось такий конфіг:
server { servername blah-blah; location / { set $addr "[2a00:ab00:103:0f:00:00:XXXX:XXXX]"; proxy_pass http://$addr; proxy_set_header Host $host; proxy_redirect off; } }
У попередніх версіях nginx такий фокус не вмів і скаржився, що в конфігу помилка. Тому плюйте в обличчя тому, хто каже, що весь софт підтримує IP6 вже 20 років, а всі гальмують і чомусь не юзають. Не підтримує ніхуя.
Далі пішли танці вже з тим нжынксом, який власне обробляє трафік і потім пхає в додаток.
Як було налаштовано раніше:
[code]
/etc/nginx/sites-available/default:
[/code]
... server { listen 80; ## listen for ipv4; this line is default and implied } ...
/etc/nginx/sites-available/blahhost.conf server { server_name blah-blah;
location / { ... } }
Здавалося б, додати рядок listen [::]:80 default ipv6only=on у головному конфігу (там же де listen 80), а далі воно само розбереться. А ніхуя подібного.
По-перше, треба дійсно додати цей рядок у дефолтному конфігу, після чого додати його скорочену версію в конфіг кожного віртуального хоста. І звичайний listen 80 не забути скрізь, під час транзишину трафік йтиме обома типами.
[code]
/etc/nginx/sites-available/default:
[/code]
... server { listen 80; ## listen for ipv4; this line is default and implied listen [::]:80 default ipv6only=on; ## listen for ipv6 } ...
/etc/nginx/sites-available/blahhost.conf server { server_name blah-blah; listen 80; listen [::]:80;
location / { ... } }
Якщо додати тільки [::]:80 у файл віртуального хоста — відвалиться IP4, якщо додати тільки в дефолтний — IP6 піде в якийсь девнул, а не туди, де описаний відповідний сервернейм.
Клаудфларовські товарищі реалізували сумнівну хуйню, поєднавши редактор DNS зі списком бекендів.
Ось наприклад:
someserver A 46.182.27.200 somerserver AAAA 2a00:ab00:103:0f:00:00:XXXX:XXXX
Якщо просто додати дві такі записи і включити їм режим проксі (жовта хмарка), то справжні адреси у відповіді DNS сервера будуть замінені на адреси фронтендів клаудфлайра, а трафік клієнтів, які прийшли на фронтенд по IP4 піде на першу адресу, трафік клієнтів, які прийшли по IP6 піде на другу. Звичайна прокся, ніякого 4to6 або 6to4:
[code]
[CLIENT](IP6) -> (IP6)[CFLARE](IP6) -> (IP6)[BACK]
[CLIENT](IP4) -> (IP4)[CFLARE](IP4) -> (IP4)[BACK]
[/code]
Далі починається магія. Якщо в налаштуваннях клаудфларовської адмінки натиснути ручку "Enable IPv6 support", то прокся почне анонсувати IP6 адреси навіть для тих хостів, яким прописаний тільки IP4 адрес, перетворюючи сервіс на 6to4 проксю:
[code]
[CLIENT](IP4) -> (IP4)[CFLARE](IP4) -> (IP4)[BACK]
[CLIENT](IP6) -> (IP6)[CFLARE](IP4) -> (IP4)[BACK]
[/code]
Це зроблено на випадок, якщо клієнт розумний, а сервер тупий. Мені ж знадобилася зворотна фігня, коли клієнт тупий, а сервер жадібний.
Очевидне рішення було таке:
somerserver AAAA 2a00:ab00:103:0f:00:00:XXXX:XXXX
Додаємо хосту тільки AAAA запис, натискаємо на жовту хмарку і радіємо. Потім перестаємо радіти, тому що сервіс ніхуя не анонсує A запис для цього хоста. У підсумку клієнт приходить, думає що нічого немає і йде. Ой.
[code]
[CLIENT](IP6) -> (IP6)[CFLARE](IP6) -> (IP6)[BACK]
[CLIENT](IP4) -x-> 永恒无效
[/code]
Але є дуже тупий хак. Можна додати обидві записи, зберегти налаштування, потім зайти ще раз і одну прибрати. Сервер продовжуватиме анонсувати A запис, але гнати трафік на IP6 бекенд.
Після редагування якогось іншого шматка зони магія ламається і треба перезаклинати заново.
Наступний камінь полетить у город селектела за зручність транзишина.
При створенні віртуальної машини вона отримує діапазон IP6 адрес, частина якого схожа на IP4 адресу цієї ж машини:
IP4 46.182.27.206 IP6 2a00:ab00:100:46:182:27:206:0000/48
Ну типу зручно.
Поставили машину, налаштували адресу з цього діапазону, налаштували сервіси, протестували що ця шайтан-арба працює.
Натискаємо кнопочку "прибрати IP4" — хуууяк, IP6 адреса одразу змінилася, тому що старий діапазон має піти тому, хто отримає відповідний IP4 адрес.
Пишемо в техпідтримку, що це адок і незручно, техпідтримка чесно пояснює механіку цього процесу. Все тлен, майбутнього немає.
У результаті виходить ось так:
[code]
[CLIENT](IP4) -> (IP4)[CFLARE ](IP6) -> (IP6)[WWW]
[CLIENT](IP6) -> (IP6)[CFLARE ](IP6) -> (IP6)[WWW]
[CLIENT](IP6) -> (IP6)[SSH]
[/code]