IPv6-прокси для Android: почему приложения игнорируют системные настройки и как это обойти
Содержание
- Системный прокси — иллюзия контроля
- Почему так происходит
- Обход через VPN-интерфейс
- Реализация на Python
- Здесь — обработка пакета и отправка через прокси
- Для демонстрации просто выводим длину
- Прозрачный прокси на iptables
- IPv6 и DNS-проблемы
- Приложения, которые делают это правильно
- Как проверить, что прокси работает
- Практический пример: настройка V2Ray на Android
- Итог
Системный прокси — иллюзия контроля
Выставил прокси в настройках Wi-Fi. Подключился. Открыл браузер — работает. Открыл приложение банка — соединение ушло напрямую. Знакомая картина?
Android разделяет трафик на две принципиально разные категории: тот, что идет через системный прокси, и тот, что игнорирует его на уровне ядра. Системный прокси в Android — это не глобальный шлюз, а просто набор переменных, которые приложения должны сами прочитать и использовать. Никакого принудительного перенаправления на уровне сетевого стека нет.
HTTP-прокси, указанный в настройках Wi-Fi, работает только для приложений, которые явно обращаются к `ProxyInfo` через `ConnectivityManager`. Остальные — особенно нативные приложения с собственными сокетами — даже не подозревают о его существовании.
Почему так происходит
Android построен на Linux, но сетевой стек настроен иначе. В Linux есть iptables и прозрачное проксирование. В Android — нет root-доступа к этим механизмам из обычного приложения.
Причина номер один: многие приложения используют собственную реализацию сетевых вызовов. Например, игровые движки (Unity, Unreal) работают через нативные сокеты. Они не читают системные настройки прокси — им проще открыть TCP-соединение напрямую, минуя Java-абстракции.
Причина номер два: HTTP-прокси не умеет работать с UDP. А DNS-запросы, QUIC, WebRTC — это UDP. Системный прокси на Android — это HTTP-прокси. Он физически не может обработать UDP-трафик. Приложения, использующие QUIC (YouTube, Chrome, Instagram), просто не видят смысла в прокси, который не поддерживает их транспорт.
Причина номер три: Android 5.0+ требует, чтобы приложение явно запрашивало разрешение `android.permission.INTERNET` и при этом не имело запрета на прямые соединения через `android:usesCleartextTraffic`. Но даже с этим разрешением приложение может игнорировать прокси — это абсолютно легально с точки зрения API.
Обход через VPN-интерфейс
Единственный способ заставить Android гонять весь трафик через прокси — создать виртуальный сетевой интерфейс. Это ровно то, что делает `VpnService`. Приложение поднимает TUN-интерфейс, забирает себе весь IP-трафик и уже сама решает, что с ним делать: отправлять через прокси, через VPN или вообще блокировать.
Схема работы такая:
1. Приложение создает TUN-интерфейс через `VpnService.Builder`
2. Android перенаправляет весь трафик (включая UDP и TCP) в этот интерфейс
3. Приложение читает пакеты, разбирает их и отправляет через прокси-соединение
4. Ответы возвращаются обратно в TUN-интерфейс
Это не прокси в классическом смысле. Это полноценный шлюз, который может обрабатывать любой трафик. Именно так работают все популярные приложения-прокси: NetGuard, Shadowsocks, V2Ray, ProtonVPN и многие другие.
Реализация на Python
Простейший пример — SOCKS5-прокси для IPv6. Ниже — рабочий код, который поднимает TUN-интерфейс и гоняет через него трафик.
```python
import socket
import struct
import fcntl
import os
TUNSETIFF = 0x400454ca
IFF_TUN = 0x0001
IFF_NO_PI = 0x1000
def create_tun():
tun = os.open("/dev/net/tun", os.O_RDWR)
ifr = struct.pack("16sH", b"tun0", IFF_TUN | IFF_NO_PI)
fcntl.ioctl(tun, TUNSETIFF, ifr)
return tun
def configure_tun(tun_name):
os.system(f"ip addr add 10.0.0.1/24 dev {tun_name}")
os.system(f"ip link set {tun_name} up")
os.system(f"ip route add default dev {tun_name} table 100")
os.system(f"ip rule add from all lookup 100 priority 1000")
def main():
tun = create_tun()
configure_tun("tun0")
while True:
packet = os.read(tun, 65535)
Здесь — обработка пакета и отправка через прокси
Для демонстрации просто выводим длину
print(f"Packet: {len(packet)} bytes")
os.write(tun, packet)
if __name__ == "__main__":
main()
```
Код требует root-доступа. На Android без root можно использовать только `VpnService` — он не требует root, но и работает через Java API, а не через прямой доступ к TUN.
Прозрачный прокси на iptables
Если у вас есть root, можно пойти другим путем. Настроить iptables так, чтобы весь трафик принудительно уходил в прокси-приложение. Это классическая схема прозрачного проксирования.
```bash
iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner 1000 -j REDIRECT --to-ports 8080
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 8080
ip6tables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports 8080
ip6tables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 8080
```
Здесь `--uid-owner 1000` — это правило для конкретного приложения. Без него можно перехватывать весь трафик, но тогда прокси должен уметь обрабатывать HTTPS-соединения с MITM, а это отдельная большая тема.
IPv6 и DNS-проблемы
Отдельная боль — DNS. Системный прокси на Android не умеет обрабатывать DNS-запросы, которые идут через UDP. А при использовании IPv6 DNS-запросы часто уходят напрямую, минуя прокси, потому что DNS-серверы IPv6 не входят в цепочку проксирования.
Решение: поднимать локальный DNS-сервер (например, dnsmasq) на TUN-интерфейсе и принудительно перенаправлять все DNS-запросы на него. Только так можно гарантировать, что DNS не утечет мимо прокси.
```bash
iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 10.0.0.1:53
iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 10.0.0.1:53
ip6tables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination fd00::1:53
```
Приложения, которые делают это правильно
NetGuard — работает через VpnService, умеет фильтровать трафик по приложениям, поддерживает IPv4 и IPv6. Shadowsocks — использует собственный протокол шифрования, работает через VpnService. V2Ray — поддерживает множество протоколов, включая VMess, VLESS, Trojan, Shadowsocks. Все они используют VpnService, потому что это единственный легальный способ перехватить весь трафик без root.
Есть и более специфичные решения. Например, для игры в региональные версии мобильных игр часто используют прокси на уровне VPN-интерфейса с фильтрацией по IP-адресам игровых серверов. Трафик к другим адресам идет напрямую, а к игровым — через прокси. Это снижает задержку и не ломает работу других приложений.
Как проверить, что прокси работает
Проще всего — посмотреть на внешний IP-адрес. Если после настройки прокси внешний IP изменился, значит, трафик действительно идет через прокси. Но это не всегда достаточная проверка — некоторые приложения могут отправлять часть трафика напрямую.
Более надежный способ — перехват DNS-запросов. Если приложение отправляет DNS-запросы напрямую, минуя прокси, значит, оно использует собственный DNS-резолвер, и часть трафика уходит мимо. Проверить это можно с помощью tcpdump или Wireshark.
```bash
tcpdump -i any -n port 53
```
Если вы видите запросы от приложения, которое должно ходить через прокси, — значит, прокси настроен неправильно. Скорее всего, приложение использует свой DNS-резолвер, и нужно перенаправлять DNS на уровне iptables.
Практический пример: настройка V2Ray на Android
V2Ray — самый гибкий инструмент для обхода блокировок. Настройка через VpnService позволяет гонять через прокси весь трафик, включая IPv6. Минимальная конфигурация для проксирования всего трафика:
```json
{
"inbounds": [
{
"port": 1080,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"udp": true
}
}
],
"outbounds": [
{
"protocol": "vmess",
"settings": {
"vnext": [
{
"address": "proxy.example.com",
"port": 443,
"users": [
{
"id": "uuid",
"alterId": 64
}
]
}
]
}
}
]
}
```
Этот конфиг поднимает локальный SOCKS5-прокси на порту 1080. VpnService перенаправляет весь трафик в этот прокси, а он уже отправляет его на удаленный сервер. Для IPv6 нужно добавить `"address": "proxy.example.com"` с IPv6-адресом или настроить DNS-резолвинг для получения AAAA-записи.
Итог
Системный прокси на Android — это полумера. Он работает только для приложений, которые согласны его использовать. Остальной трафик уходит напрямую. Если нужен реальный контроль над трафиком — только VpnService, только TUN-интерфейс, только принудительное перенаправление всего трафика.
Настройка через VpnService — это не сложно, но требует понимания того, как работает сетевой стек Android. Зато результат — полный контроль над всеми соединениями, включая UDP, DNS и IPv6. Именно так работают все серьезные прокси-приложения на Android, и именно так стоит делать, если вам нужен надежный обход блокировок.