WARP 속도의 미학 : Linux Transparent Proxy (TPROXY)

(Last Updated On: May 31, 2020)

이전 포스트에서 나는 CloudFlare의 서비스 WARP가 빠른 이유에 관해서 분석하였다.

 

어떻게 구현하지?

사실 위의 Spectrum 과 관련한 Challenge글을 번역기로 대충 읽고 말았던 것이 헤맸던 가장 큰 이유였 던 것 같다.

기존의 VPN에 NAT을 사용했다면 Layer-3의 포트 주소 변환(NAT)으로 부를 수 있겠다. 그러나 연결되는 PORT의 TCP의 세션의 흐름까지 변경해버리는 프록시는 Layer-4의 주소변환(NAT)인 셈이다. 주소만 변경되지 않고 TCP와 관련한 모든 메커니즘의 흐름이 변한다. 사실 Layer-4는 로드 밸런싱이나 원격 서버를 숨길 때나 사용한다.

그러나 문제는 이것을 대체 어떻게 구현하냐는 것 이였다.우리가 웹 사이트 접속할 때 HTTP나 SOCKS5 등의 프록시 접속이 가능하다는 것이 떠오른다. 내 목표는 우선은 웹 사이트에 접속할 때 만이라도 프록시로 연결 될 수 있다면 정말 기쁠 거라고 생각했다. 그것만으로도 속도가 늘어날 수 있으니까.

다시 의심되기 시작했다

이걸 리눅스 커널레벨의 소스 코드 수정하는 일 없이 구현할 수 있는게 맞는가? 싶어서 CloudFlare WARP Challenge 글에 올려져 있는 구조를 다시 보기 시작했다.

cloudflare-warp-technology-structure
CloudFlare 블로그에 올려져있는 WARP의 구조

구조를 보면 Warp VPN는 WireGuard tunnel 이며 중간에 WARP Proxy가 있다. 여기서 Warp VPN – WireGuard tunnel은 NAT을 수행할 것이고 Proxy는 우리가 웹브라우저에서 사용하는 브라우저에  있는 프록시를 뜻 할 것이다.

 

Squid: Optimising Web Delivery ?

사용자 (호스트)의 데이터를 PROXY로 연결시켜서 데이터 캐싱도 가능케 해주는 서버 프로그램이다. yum install squid 로 설치 후 이 룰을 적용해 개인적인 VPN 트래픽을 iptables 룰로 연결 시켜보았다.

80포트를 3128로 TProxy 를 설정한 결과는 성공적이였다. 그러나 아직 80포트 (HTTP 서비스)에만 적용했을 뿐이고 HTTPS는 아직 적용되지 않았다.

그러나 여기서 의문점이 생긴다. 80포트를 3128포트로 이동시키는 것은 알겠는데 443포트를 3128포트로 이동시키면 Squid Cache Server는 기존의 포트를 알아차릴 수 있을까? 별도의 메모리 없이는 한번 변환 한 포트는 날라가버려서 더 이상 목적 포트를 알 수 없을 거라고 생각됐다.

역시나 443 포트를 3128포트로 연결 했더니 결과는 생각하던 바였다.

transparent-proxy-ssl-protocol-error

CentOS 7의 기본 repo에서 제공하는 Squid의 버전이 3.x 여서 4.x 소스 설치를 해 봤지만. 어떤 이유에선가 대몬의 시작부터 오류가 나서 서버조차 열리지 않았다.

더 이상 squid는 사용할 수 없다고 판단하고 사용을 포기하였다.

 

사막의 오아시스

아무래도 패킷을 다루는 소스코드는 구현하는데에는 무경험자에겐 많은 비용이 들기 때문에 어떻게든 Transparent Proxy (TPROXY)의 서버를 찾고 싶었다. Squid는 더 이상 논외가 되었다.

구글링을 하던 도중 Transparent Proxy용으로 Go언어로 만들어진 서버소스가 하나 있었다.

go-any-proxy is a server that can transparently proxy any tcp connection through an…

당장에 없던 golang을 설치하고 빌드 후 1100 포트로 오픈 후 실행시켜보았더니

된다..!!

혹시나 싶어 잠시 환청이였는가 싶어서 서버를 꺼보았다.

transparent-proxy-via-go-any-proxy

서버를 끄자마자 접속이 끊긴 것을 보니 정상작동을 인지할 수 있었다.

어떻게 동작하나?

위에서 의문이였던 것이 포트를 변경해버리면 기존의 포트가 날라가 버려서 목적지를 알 수 없게 되어 버리는 것이였는데 go-any-proxy의 서버 소스를 확인하니

알 수 없는 외계어로 syscall을 통해 기존의 패킷의 Destination 포트를 알아내고 ipv4, port, clientConn, err := getOriginalDst(clientConn)  포트를 반환한 뒤 작성한  함수를 통해 프록시 서버를 구현한 것 이다.

 

마지막으로 목표인 과연 내가 CloudFlare WARP 에서 느꼈던 속도처럼 나올까? 싶어서 바로 throughput 측정을 했다.

분명 해외망이 빠른 가상서버의 회사기에 속도가 빠를 수 있다. 하지만 독일까지 업로드가 100Mbps 이상 나오는 경우는 드물었다.

 

본격적으로 속도 테스트

이 TPROXY를 통한 TCP 가속은 국내 사이트에서는 체감이 없을 가능성이 높다. TCP 데이터 전송에 있어 RTT가 크게 변동하지 않기 때문이다.

해당 속도측정은 외국사이트에 측정하기 때문에 극단적인 시나리오일 수 있겠지만 내가 주로 접속하는 사이트가 외국사이트였기 때문에 극히 평범하다.

속도측정 서버 상태가 안정적일 것 같은 회사를 사용

측정하는데 애초에 측정 서버가 항상 바쁘거나 하면 속도 테스트의 결과 수치의 신빙성이 떨어진다. Tier-1 의 대형 백본 회사의 서버를 이용했다.

tproxy-tcp-accelerated-vpn

결과는 참담했다…

미국서버는 어떨까

아시아의 대부분의 트래픽을 담당하는 미국의 로스엔젤레스의 서버로 테스트 해 보았다.

주로 속도측정사이트는 최대 throughput을 내기 때문에 TCP 세션을 여러 번 접속해서 속도 측정을 한다. 그래서 속도측정 사이트와 실제 다운로드 속도가 다른 일이 있다. 속도의 차이는 자릿 수 마저 바뀔 정도였다. 16Mbps에서 118 Mbps로 변한 것은 같은 VPN을 사용하더라도 구현에 따라 속도는 얼마든지 차이날 수 있다는 것이다.

High Latency

러시아의 하바롭스크 (Khabarovsk)의 속도를 비교했다. 이번에는 Multiconnection으로만 테스트 했다. 다운로드 속도는 2배 증가했고 업로드 속도는 현저히 두드러졌다.

 

이유는 무엇일까

TCP 혼잡제어. 오류제어 알고리즘 및 쓰로우풋은 RTT에 매우 의존적이다. 사실 이번 테스트에서 리눅스 서버의 혼잡제어로 Google BBR 을 사용해서 기존의 알고리즘은 어떨진 모르겠는데 Windows 운영체제는 특히나 리눅스처럼 단순🤔? 하지 않고 사용자가 트윅 할 수 있는 네트워크 옵션도 제한적이기 때문으로 추측한다.

VPN without Transparent Proxy
Transparent Proxy가 적용되지 않았을 때
VPN with Transparent Proxy
Transparent Proxy가 적용되었을 때

그림으로 TCP 데이터의 흐름을 그려보았지만 양이 적어서 그런지 오히려 그림으로는 설명이 안 되는 것 같다. 하지만 분명 버퍼의 존재와 양쪽 TCP 세션 간 TCP 흐름을 적절히 흐르기 때문이라고 생각된다.

Google BBR의 Throughput

APNIC에서 기존의 CUBIC 알고리즘과 Google BBR의 RTT에 따른 성능 비교를 한 글이 있다. 실제로 low latency에서는 크게 변화가 없지만 High-Latency에서는 2배 이상의 쓰로우풋 차이가 나는것을 알 수 있다.

 

https://blog.apnic.net/2020/01/10/when-to-use-and-not-use-bbr/

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *