서론
이 포스트에서 통신사의 테더링 제한을 우회하는 방법을 설명했었다.
그러나 저 설정 방법은 자급제 안드로이드 기기(외산 포함)가 아닌 단말기에선
구현할 수가 없다는 한계가 있었다.
물론 저렇게 APN을 수정하지 않아도 기기 안에서 프록시 서버를 열어
테더링의 트래픽을 기기의 트래픽으로 만드는 방법은 여럿 존재한다.
안드로이드에선 PdaNet+와 Netshare라는 앱으로 해당 기능을 구현할 수 있다.
아이폰에서는 iSH라는 유료 앱에서 아래의 명령을 입력하면 유사하게 구현이 가능했다.
apk update && apk add tinyproxy && sed -i 's/^Allow 127.0.0.1$/Allow 0.0.0.0\/0/' /etc/tinyproxy/tinyproxy.conf && echo -e "tinyproxy &\ncat /dev/location > /dev/null &\nps aux | grep tinyproxy | grep -v grep\ngrep '^Allow' /etc/tinyproxy/tinyproxy.conf" >> ~/.profile && source ~/.profile
클라이언트 단에서 추가적으로 프록시 설정을 해줘야 하는 것에 대해선 설명을 생략한다.
아무튼 이렇게 되면 웹 브라우징 같은 건 잘 되는데 뭔가 안되는 게 하나 둘 보일 것이다.
카카오톡이나 디스코드, 또 UDP 통신을 쓰는 다양한 서비스들이 정상적으로 작동하지 않을 것이다.
이는 프록시 서버가 TCP 패킷만을 넘겨서 그런 것이며,
TCP 통신이 아닌 모든 통신은 통신사가 설정한 공유데이터를 차감시키거나,
없다면 되지 않을 것이다.
방법이 없을까?
많은 사람들이 이 대목에서 피로감을 느끼고 포기를 한다.
인터넷이 되기는 한다는 것에 만족하고 그냥 쓰거나,
이에 만족하지 못한다면 라우터를 추가로 구입하거나,
또는 셀룰러 모델로의 교체를 하는 식으로 말이다.
나 또한 아이폰을 주력으로 쓰게 된 이후로는 위 2, 3번째 선지를 계속 만지작거렸다.
경험상 전자보다는 후자가 더 쾌적했다.
전자는 중국제 라우터가 시장을 잠식한지 오랜 시간이 지났으며,
그 성능과 사용시간에 신뢰성을 느끼기가 어려웠다.
더구나 추가적인 단말기라는 측면에서
외부에서는 미니멀리즘을 지향하는 내 취향에 맞지 않았다.
카페에 바리바리 싸들고 와서 전개하는 건 성가신 일이다.
그런 걸 하기엔 집이라는 좋은 장소가 있다!
후자는 다 좋은데 기기가 너무 비싸고,
무엇보다 멀쩡히 쓰는 폰 회선을 냅두고
높은 요금제의 추가적인 개설을 요한다.
메인 회선을 저렴하게 바꾸고 기기에 몰아주는 방법도 있지만,
영상을 많이 보고 싶은 사람이면 별로 내키지 않을 것이다.
UDP over TCP
찾아보니 TCP 터널 안에 UDP 패킷을 집어넣는 것이 가능은 하다고 한다.
UDP의 이점을 상당부분 훼손하는 바보같은 방법이지만 그래도 써야만 한다면…
나의 경우 UDP 통신을 활용하는 Wireguard VPN과 Moonlight가 필수적이기 때문에
이 부분은 나의 구미를 당겼다.
그러나 이를 위해서는 서버와 클라이언트에 모두
UDP over TCP가 가능하도록 환경을 구성해야 한다.
지금은 아이폰이 라우터고, 거기에 프록시 서버까지 돌리고 있는데
거기에 추가적으로 해당 구성이 가능해보이지 않았다.
서버를 돌릴 앱인 iSH가 Alpine 리눅스를 가상으로 돌려 기능을 제공하는데,
문제는 네트워크 어댑터 관련 권한 문제가 있어
프록시 서버 주소조차 특정을 할 수가 없다.
때려 맞춘 주소로만 TCP 통신이 가능하다.
일반적으로 접속을 시도할 때도 이럴진데,
사전에 주소와 포트를 지정하고 UDP 패킷이 이 터널을 지나도록
구성하는 것은 난도를 산으로 올려버리는 짓 같았다.
Socks5?
Socks는 Socket Secure의 약자로 전송계층(L4)과 응용계층(L7)에서 작동한다.
HTTPS와는 다르게 내부에 어떤 패킷이 들어오든 서버 <-> 클라이언트로 전달하며
최근 규격인 Socks5에서는 UDP 패킷과 인증을 지원한다.
이를 이용하여 클라이언트 발 Wireguard에 감싸진 Moonlight의 UDP 패킷을
프록시 서버를 통해 정상적으로 전달할 수 있다.
Socks5 Server 구현하기
iOS Socks Server를 이용하면 iOS 단말기에서 Socks5를 지원하는 서버를 돌릴 수 있다.
13,000원의 거금으로 Pythonista 3라는 앱을 구매해야하지만,
Pyto라는 무료 앱으로 체험해보고 결정할 수 있으므로
고민이 되는 사람들은 이 앱을 먼저 사용해보길 바란다.
위 GitHub 페이지의 내용대로 Socks.py를 앱으로 실행하면,
다음과 같이 현황판이 나온다.
현재 라우터 역할을 하는 아이폰이 Wireguard VPN으로 10.7.7.61의 주소를 받고 있는데
해당 주소로 Socks 연결이 중계됨을 알 수가 있다.
해당 VPN은 NAT를 구성하지 않아 원격을 위한 P2P 연결만을 지원하며,
때문에 해당 대역이 아닌 인터넷에는 패킷이 전달되지 못함을 알 수가 있다.
(문라이트 사진)
(연결 불량 사진)
모든 연결을 중계하도록 0.0.0.0/0으로 설정된 인터넷이 가능한 타 VPN 프로필을 켜고 접속하면
해당 주소로 내부망과 인터넷에 모두 접속할 수 있음을 알 수가 있다.
(Jellyfin 사진)
(연결 정상 사진)
만일 아이폰에서 VPN을 켜지 않았다면, 아이폰이 할당 받은 CGNAT의 주소가 뜨며
아이폰에서 접속하듯이 인터넷을 활용할 수 있다
클라이언트 설정
저렇게 연결하기 위해선 클라이언트에서도 Socks 프록시 서버에 접속할 수 있어야 한다.
아래에 있는 주소는 동일하지 않을 수 있고, 실행 화면에 뜨는 걸 기준으로 입력해야한다.
iOS의 경우
HTTP 프록시 설정에서 PAC 주소인 http://172.20.10.1:8088/wpad.dat을 입력하여 접속한다.
macOS의 경우
System Preferences를 열고 Network, Wi-Fi, Advanced 순서대로 들어가 프록시 설정에서 SOCKS Proxy를 체크한다.
주소를 입력하는 부분에 http://172.20.10.1:9876을 치고 접속한다.
Windows와 Linux경우
시스템에서 제공하는 프록시 서버 설정 단에서 PAC 주소인 http://172.20.10.1:8088/wpad.dat을 입력하여 접속한다.
Android의 경우
Socks 클라이언트 역할을 해줄 앱으로 http://172.20.10.1:9876에 접속한다.
인증 정보가 있다면 Shadowsocks 앱도 괜찮지만,
나는 Tun2Socks 앱을 사용했다.
- GitHub 설명에서는 Socks 프록시를 지원하지 않기 때문에 HTTP 프록시로 연결하라 했지만,
이처럼 VPN 슬롯을 통해서라도 Socks 프록시로 연결하는 방법이 존재한다.
결론
백그라운드에 인색한 iOS의 특성상 Pythonista 3 앱을 항상 켜야 한다는 불편함이 있다.
그러나 타 방법과 다르게 확실히 UDP 통신을 가능케하고,
특별히 UDP 패킷의 드랍율이 높진 않아 Moonlight와 같은
무거운 트래픽을 발생시키는 앱들도 감당이 가능했다.
추가적인 장비 도입이 귀찮은 아이폰 유저라면 한번쯤은 시도해 볼 법 하다.