이전 게시글과 내용이 다소 중복되므로 이전 게시글을 함께 참고할 것을 권장한다.
한 서버에서 여러 오픈된 서비스를 돌리는 경우 각 서비스에 접근할 때마다 매번 포트를 써줘야하는 불편함이 있다.
DNS에 도메인을 등록하고싶어도 DNS는 IP를 기반으로 하기 때문에 필자의 경우에는 사용할 수 없다.
이에 서버 내부에 프록시서버를 두는 방법을 생각해보았다.
필자가 사용할 프록시서버는 HAProxy이다.
HAProxy(High-Availability Proxy)는 고가용성을 지원하는 오픈소스 리버스 프록시 서버이자 L4/L7 로드밸런서이다.
워낙 유명하고 잘 사용되다보니 굳이 이 글에서 HAProxy에 대해 설명할 이유는 없어 보인다.
좋은 블로그 게시글들이 많으니 이들로 설명을 갈음한다.
본래 HAProxy는 로드밸런싱과 무중단 서비스를 위한 솔루션이지만 필자는 L7 스위치로서의 기능을 위해 HAProxy를 도입하였다.
이제는 필자의 서버에서 제공하는 여러 서비스들을 기존처럼 포트로 접근하지 않고 도메인을 통해 접근할 것이다.
HAProxy 설치
필자의 경우 Centos7에서 yum으로 받을 수 있는 최신 버전이 1.5.18-9였고 필자가 참고하던 docs는 haproxy-2버전이었기에 상위버전의 haproxy를 설치하였다. (22.02.02 기준)
공식 홈페이지에서 적당한 버전을 찾아 내려받으면 된다.
필자는 2.4.12 LTS 버전을 받아 설치하였다.
$ curl -o haproxy-2.4.12.tar.gz http://www.haproxy.org/download/2.4/src/haproxy-2.4.12.tar.gz $ yum -y install make gcc perl pcre-devel zlib-devel openssl-devel $ tar -zxvf haproxy-2.4.12.tar.gz haproxy-2.4.12 && cd haproxy-2.4.12 $ make TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 $ make install
HAProxy가 설치되었다.
이제 HAProxy를 운용하기 위한 몇 가지 설정이 필요하다.
먼저 계정을 생성한다.
$ sudo useradd -r haproxy
그리고 소프트링크를 만들어 일반사용자도 사용할 수 있도록 한다.
$ sudo ln -s /usr/local/sbin/haproxy /usr/sbin/haproxy
그 후, HAProxy를 운용하기 위한 서비스를 준비한다.
$ sudo cp haproxy-2.4.12/examples/haproxy.init /etc/init.d/haproxy $ sudo chmod 755 /etc/init.d/haproxy $ sudo systemctl daemon-reload $ sudo chkconfig haproxy on
마지막으로 HAProxy 설정파일을 작성한다.
다행히도 설정파일 또한 설치파일에 들어있다.
다만 설정파일을 예시파일이므로 설정파일 중 global과 defaults 부분만을 사용하고 나머지는 삭제한다.
$ sudo cp haproxy-2.4.12/examples/basic-config-edge.cfg /etc/haproxy/haproxy.cfg
HAProxy 기초 설정
HAProxy는 service 형태로 운용된다.
HAProxy를 설치한 직후에는 service가 비활성화된 상태이기 때문에 HAProxy를 가동하려면 service를 실행해주어야 한다.
$ systemctl enable haproxy $ systemctl start haproxy
HAProxy 도메인 설정
필자가 운영하는 가상의 서버 foo.com에서 운영되는 두 서비스를 HAProxy를 통해 리디렉팅해보자.
서비스 정보는 다음과 같다.
- aaa.foo.com:12345 (tcp 기반 서비스)
- bbb.foo.com:8080 (http 기반 서비스)
aaa는 12345 포트를 사용하는 tcp 기반 서비스이며 bbb는 8080 포트를 사용하는 http 기반 서비스이다.
필자는 외부에서 12345 포트와 8080포트에 접근하지 못하도록 1234포트와 80포트를 두어 리디렉팅하였다.
이 경우 12345와 8080포트는 닫아두고 1234와 80포트만 열어두면 된다.
당연히 여러가지 응용이 가능하다.
(참고로 TCP의 경우 ACL 구문을 통한 접근제어가 되지 않는다. 향후 추가로 글을 달아놓을 예정)
예를 들어 8080포트를 오픈하고싶지는 않으나 외부에서 접근하고싶은 경우에는
8080포트를 막아두고 9090포트를 오픈한 후 9090포트로 들어오는 트래픽을 이 절에서 설명하는 방식을 통해 8080포트로 리디렉팅해주면 된다.
그 결과 사용자는 사용자가 설정한 도메인 네임을 통해 해당 서비스에 접근할 수 있다.
당연 도메인을 모르는 사용자는 8080와 9090포트 어느 것을 사용하더라도 해당 서비스에 접근할 수 없다.
<생략> frontend aaa_fe mode tcp bind :1234 acl is_aaa hdr_end(host) -i aaa.foo.com use_backend aaa_servers if is_aaa frontend bbb_fe mode http bind :80 acl is_bbb hdr_end(host) -i bbb.foo.com use_backend bbb_servers if is_bbb backend aaa_servers mode tcp server server1 127.0.0.1:12345 backend bbb_servers balance roundrobin server server1 127.0.0.1:8080
acl 구문은 접근통제를 위한 구문으로 aaa.foo.com이나 bbb.foo.com 외 도메인을 통해 접근하는 요청을 모두 거절한다.
마지막으로 aaa.foo.com와 bbb.foo.com의 DNS를 foo.com로 등록한다. (CNAME)
이제 귀찮게 foo.com:12345로 접근하지 않고 aaa.foo.com로 접근하면 foo.com의 12345 포트 서비스에 접근할 수 있다.
이제 다음 게시글에서 HAProxy 서버에 SSL 인증서를 적용해보자.
SELinux 이슈
참고로 기존 서비스 포트를 바꿀 때 방화벽 뿐만 아니라 SELinux도 신경써주어야 한다.
잘 되던 서비스가 포트 바꿨다고 동작이 안될때는 semanager 유틸리티를 통해 서비스 포트가 열려있는지 확인하자.