하나의 포트를 이용하여 여러개의 서비스를 돌릴 때 haproxy를 이용할 수 있다.
하지만 이런 경우 실제 서비스하는 서버입장에서는 실제 클라이언트 IP를 알 수가 없다.
(HTTP프로토콜에 한해서는 Header에 실제IP를 기입할 수 있다)
그렇게 때문에 필요한 경우 transparent 기능을 이용해야 한다.
보통은...
INTERNET ------- (외부망)haproxy(내부망, default gateway역할) ------ Servers
이런식으로 haproxy가 게이트웨이에서 동작할텐데 나는
INTERNET ----- GATEWAY(내부망) ---------- haproxy + 로컬서버
+----- Servers
이런 식이다.
이런 경우 transparent가 동작하지 않게 된다.
일단 transparent의 원리는 이렇다.. (잘 몰라서 패킷 뜯어보고 별 삽질을..ㅠㅠ)
haproxy가 원하는 포트로 LISTEN을 하고 있다.
외부클라이언트가 haproxy에 연결된다.
haproxy는 일치하는 backend에 연결한다.
* 이 때 bind socket의 주소를 외부클라이언트주소로 바꾸고 backend에 연결을 시도한다.
(보통의 경우) 바뀐 source ip 의 패킷이 backend에 전송된다.
backend에서 해당 패킷을 처리 한 후 source ip를 destination ip로 해서 결과를 전송한다. (기본적인 통신구조)
haproxy가 게이트웨이에 있기 때문에 5번의 패킷은 자연스럽게 haproxy가 다시 받을 수 있다.
haproxy는 받은 패킷을 다시 외부클라이언트로 전송한다.
그런데 나는 haproxy와 동일한 서버에 있는 backend에 접속하려고 했더니 netstat에는
haproxy to backend : SYN_SENT
backend to haproxy : SYN_RECV
이 상태로 멈춰있었다. tcpdump로 보니까...
haproxy -> backend : lo (Loopback)으로 통신하고
backend -> haproxy 으로 가야할 것은 : ens32 (default gateway설정된 NIC)로 보내어 외부 인터넷 어디론가로 보내고 있었다. 이러니 안될수밖에...
이러한 상황에서는
iptables -t mangle -N DIVERT # 이건 기본
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT # 이건 기본
iptables -t mangle -A OUTPUT -s 127.0.0.1/32 -p tcp -m tcp --sport 1234 -j DIVERT # 추가된것!
iptables -t mangle -A DIVERT -j MARK --set-xmark 0x1 # 이건 기본
iptables -t mangle -A DIVERT -j ACCEPT # 이건 기본
# 추가로 ip rule 추가해야 하는데 그건 기본 haproxy 메뉴얼에 있음
이렇게 iptables mangle의 OUTPUT필터에서 패킷을 mark해서 밖이 아닌 haproxy으로 되돌아 가도록 하면 된다.
하지만 haproxy -> 같은 내부 네트워크 서버 인 경우에는???
이런 transparent는 불가능하다.. haproxy에 의해 바뀐 src ip를 받은 backend는 그게 haproxy가 준건지 외부에서 온건지 알 수 없기 때문에..
이런 경우는 그냥 http header를 이용해서 client ip를 같이 보내주는 수밖엔 없다.
'개발 및 운영' 카테고리의 다른 글
Jenkins gitlab연동 gradle프로젝트 자동빌드&도커빌드 (0) | 2019.08.05 |
---|---|
EJBCA SSL인증서 갱신(재발급) (0) | 2019.07.10 |
sslh & openvpn connection-reset 문제 (0) | 2019.07.09 |
Nitrokey HSM key import (0) | 2019.06.08 |
postfix restrictions 에 대해.. 끄적끄적 (1) | 2019.05.28 |
댓글