Маршрутизація за політикою проти SOCKS: який рівень насправді проксіює трафік
Маршрут до порту SOCKS — це не сеанс SOCKS. Порівняйте налаштування проксі на рівні застосунку, адаптер IP-до-проксі та маршрутизований шлюз за рівнем, який виконує перетворення.
Ви додали маршрут за політикою, який надсилає трафік клієнта VPN на хост, де на порту 1080 працює слухач SOCKS. Пакети надходять, слухач нічого не записує, і з'єднання зависає. З маршрутом усе гаразд: наступний перехід вибирає, куди йде пакет, а SOCKS — це розмова, яку має почати клієнт. Порівняйте три архітектури, які зазвичай мають на увазі, коли кажуть про надсилання трафіку через проксі, і стане зрозуміло, якої частини бракує у вашому налаштуванні.
Маршрутизація, DNAT і SOCKS змінюють різні речі
Маршрут за політикою переписує рішення рівня 3. Двох рядків достатньо, щоб надіслати трафік одного клієнта на вибраний наступний перехід:
ip route add default via 10.50.0.2 table 101
ip rule add from 10.77.0.2 lookup 101Після цього ядро передає пакет на 10.50.0.2, а початкове призначення все ще в заголовку IP. Якщо 10.50.0.2 — маршрутизатор, він пересилає пакет. Якщо це хост із демоном SOCKS на 1080, пакет не адресований нічому, що могло б його прийняти, і DNAT на порт 1080 теж не допомагає, бо перетворений пакет усе ще несе початкове корисне навантаження застосунку замість привітання SOCKS.
SOCKS5 починається з байта версії, списку методів, обміну автентифікацією та запиту, який називає призначення. Це дані застосунку. Ані запис маршрутизації, ані ціль netfilter їх не створюють, і в цьому порівняння в один рядок: маршрутизація вибирає шлях, SOCKS просить сервер встановити друге з'єднання.
Перший випадок: застосунок сам уміє говорити SOCKS
Коли програма має налаштування проксі, це найкоротший шлях, і він не потребує змін у ядрі. Спрямуйте його на слухач, надайте облікові дані, якщо сервер їх попросить, і вирішіть, чи імена розв'язуються локально, чи передаються проксі. У curl це різні прапорці, і різниця важлива, коли призначення розв'язується лише з боку проксі:
curl --socks5 10.50.0.2:1080 https://docs.example.com
curl --socks5-hostname 10.50.0.2:1080 https://internal.example.comЗастосункам, які ігнорують змінні середовища проксі або відкривають сирі сокети, так допомогти не можна. Браузери та більшість інструментів HTTP у порядку; ігровий клієнт, демон пошти або довільний бінарний файл постачальника зазвичай ні. Межа проходить за кожним застосунком і кожним протоколом, тому цей варіант чудовий для тестування і слабкий як відповідь для всього VPN.
Другий випадок: адаптер, який перетворює IP-потоки на проксі-сеанси
Для програм, які не вміють говорити SOCKS, перетворення має відбуватися в чомусь, що завершує IP-трафік і відкриває проксі-сеанси від їхнього імені. Цей компонент володіє тунельним інтерфейсом, приймає потоки, вибрані маршрутизацією за політикою, виконує рукостискання SOCKS для кожного з них і заново збирає відповіді. Маршрут спрямовує трафік до нього; саме адаптер створює сеанс.
Прочитайте документацію, перш ніж довірити йому цілу підмережу. Багато адаптерів добре переносять TCP і обробляють UDP лише через асоціацію UDP у SOCKS5, і жоден із них не перетворює ICMP на проксі-трафік, тож успішний ping нічого не каже про шлях через проксі. DNS — інша пастка: якщо адаптер розв'язує імена локально, записи лише для внутрішнього використання розв'язуються в неправильну відповідь або взагалі ні в що.
Запобігання петлям — та операційна деталь, яка кусає. Власні з'єднання адаптера до сервера SOCKS не повинні маршрутизуватися назад в адаптер, тому його трафіку потрібен виняток у правилі або окрема адреса джерела. Помилитеся тут, і проксі-сеанс спробує проксіювати сам себе.
Третій випадок: хост насправді є маршрутизованим шлюзом
Іноді робоче налаштування взагалі не містить SOCKS. Віддалений хост пересилає пакети або виконує для них NAT, і правило на основі джерела просто вибирає його як вихід. Така схема законна, і вона пояснює, чому скопійована конфігурація працює в одній мережі й не працює в іншій: правило однакове, відсутня частина — служба пересилання на іншому боці.
Три випадки розділяються швидко. Перевірте, що саме слухає, а потім подивіться на перші байти, які доходять до хоста:
ss -ltnp 'sport = :1080'
tcpdump -ni eth0 -X 'tcp port 1080'Перший байт корисного навантаження справжнього клієнта SOCKS — 0x05, версія в привітанні. Якщо запис показує натомість початкові дані застосунку, жоден демон SOCKS не відповість, бо переговори так і не почалися. Якщо на 1080 нічого не слухає, хост — це шлюз, і питання стає таким: чи пересилає він і чи існує зворотний шлях.
Виберіть рівень за допомогою чотирьох питань
Чи має програма налаштування проксі? Скористайтеся ним і зупиніться на цьому. Чи є в трафіку UDP або ICMP, які мають вижити? ICMP несе лише маршрутизований шлюз або шлюз із NAT, а UDP потребує асоціації SOCKS5, яку підтримують обидві сторони. Чи потрібно охопити кожен процес на машині, включно з тими, які ви не можете налаштувати? Тоді потрібен адаптер, який володіє інтерфейсом і завершує потоки. Чи можете ви взяти на себе також його маршрутизацію, DNS і винятки для запобігання петлям? Якщо ні, звичайний шлюз коштуватиме дешевше в експлуатації.
Одну відмінність варто тримати чіткою. Власна опція socks-proxy клієнта VPN описує, як зовнішнє тунельне з'єднання досягає свого сервера, і нічого не каже про перетворення внутрішніх потоків клієнта. Ці дві речі постійно плутають у тому самому тікеті. Вирішіть, який зв'язок вам потрібен, перш ніж торкатися маршруту.