이전 글에서 간단히 설명한 WebClient 프록시 방식에 대해서 자세히 살펴보려한다.
먼저 우리는 보안 요구사항으로, 네이버망에 있는 서버와 API 통신을 할 때 프록시 서버를 거치도록 수정했다.
코드 작업은 간단하다. reactor.netty HttpClient 에서 제공하는 proxy 메서드를 사용해 프록시 host 와 port 만 적어주면 프록시를 거쳐서 baseUrl 에 등록된 서버로 호출된다.
HttpClient httpClient = HttpClient.create()
.proxy(it ->
it.type(Proxy.HTTP)
.host(프록시 서버 주소)
.port(443)
);
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl(원래 보낼 타겟 네이버 서버)
.build();
그런데 netty HttpProxyHandler 내부 코드를 보면 CONNECT HTTP 메서드로 요청을 보내는 것을 알 수 있다. 어떤 방식으로 프록시하는걸까?
@Override
protected Object newInitialMessage(ChannelHandlerContext ctx) throws Exception {
InetSocketAddress raddr = destinationAddress();
String hostString = HttpUtil.formatHostnameForHttp(raddr);
int port = raddr.getPort();
String url = hostString + ":" + port;
String hostHeader = (ignoreDefaultPortsInConnectHostHeader && (port == 80 || port == 443)) ?
hostString :
url;
// CONNECT HTTP 메서드로 요청을 보냄
FullHttpRequest req = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.CONNECT,
url,
Unpooled.EMPTY_BUFFER, false);
req.headers().set(HttpHeaderNames.HOST, hostHeader);
... 생략
return req;
}
결론부터 말하면 CONNECT 메서드로 웹 터널을 이용해 프록시 한다.
CONNECT 메서드는 HTTP/1.1 명세에 자세히 나와 있지는 않지만 많이 구현하는 확장기능이다.
CONNECT 메서드는 터널 게이트웨이가 타겟 서버와 포트에 TCP 커넥션을 맺고, 클라이언트와 서버 간 오가는 데이터를 무조건 전달하기를 요청한다. 아래 그림에서 클라이언트는 파이낸셜 서버, 게이트웨이는 Security Proxy, orders.joes-hardware.com 은 네이버 서버가 된다.
파이낸셜 서버(클라이언트)는 Security Proxy(게이트웨이)에 터널을 연결하려고 CONNECT 요청을 보낸다. CONNECT 메서드는 TCP 커넥션을 위해 Security Proxy(게이트웨이)에 터널 연결을 요청한다(host 는 orders.joes-hardware.com port 는 443).
TCP 커넥션이 맺어지면(위 그림 b,c,d에 해당) 터널이 연결되고 HTTP 터널을 통해 전송된 파이낸셜 서버(클라이언트)의 모든 데이터는 위에서 맺은 TCP 커넥션으로 바로 전달될 것이며, 타겟 서버로부터 전송된 모든 데이터 역시 HTTP 터널을 통해서 클라이언트에게 전달될 것이다.
그리고 터널을 통해 전달되는 데이터는 Security Proxy(게이트웨이) 에서 볼 수 없어서 Security Proxy(게이트웨이)는 패킷의 순서나 흐름에 대한 어떤 가정도 할 수 없다. 터널이 일단 연결되면, 데이터는 언제 어디로든 흘러가버릴 수 있다.
cf) Security Proxy(게이트웨이) 애플리케이션은 Squid 오픈소스를 사용한다.
참고: HTTP 완벽가이드 웹 터널
'Http' 카테고리의 다른 글
HTTP keep-alive on/off 에 따라 다른 결과가 나오는 이슈 (0) | 2022.05.29 |
---|---|
GET / POST 를 목적에 맞춰 사용하지 못한 케이스 (0) | 2021.06.18 |
Cookie SameSite Lax 모드 업데이트 정리 (0) | 2021.04.08 |
Cookie SameSite 기본편 (0) | 2021.02.05 |
https + id/pw rsa 암호화 (0) | 2021.01.31 |