April 9, 2021
By Bogeun Kim (bokunn91@gmail.com)
ISMS 심사를 수행하면서 정보 자산에서 발생되는 Outbound 요청들에 대한 관리가 필요하였다. (당연히 보안상 중요하고 필요하긴한데,,,. 말그대로 서버내에서 허용되지 않은 요청들은 모두 차단해버리겠다는 애기. 인터넷, 패키지설 등 등
)
예로 특정 서버에서 인터넷으로 API Call 을 수행하는 경우 해당 API Call 에 대한 Destination IP 및 Port 를 인지하고 방화벽 수준에서 허용된 IP/Port 만을 허용이 필요하다는 것.
그러나, 일부 API (Destination) 들은 Static IP 를 사용하는 반면 일부 API 들은 유동적인 IP를 활용하여 IP를 특정하여 허용해줄 수 없다. 특히 백신 엔진 업데이트 및 소프트웨어 패치 관련하여서는 IP 가 유동인 경우가 꽤 많은 것 같다. 이럴 때 최근의 방화벽 장비에서 지원하는 것처럼 Domain (Host) 기반으로 통제할 수 있다면 손쉽게 Outbound 를 관리할 수 있을 것이다.
AWS Security Group 및 NACL 은 모두 IP 기반의 통제만 가능하기에 이를 대체할 방법이 필요했다. 그래서 Outbound 트래픽을 위한 Proxy 서버를 생성하여 Domain 기반으로 Outbound 트래픽을 통제해보려고 한다.
도식화 & 설계
먼저 그림을 그려가면서 어떤 요구사항이 필요한 것인지 스케치 해보자.
요구사항 스케치
요구사항을 정리하면
•
'A 서버'에서 웹 요청 (Port: 80, 443) 을 할 경우
Proxy 서버 ('B 서버') 를 거쳐서 인터넷으로 접근한다.
•
Proxy 서버에서는 접근이 허용된 도메인만을 인터넷으로 연결시킨다. (White-List 관리)
Proxy 서버 구축/활용 도식화
구현
Proxy 서버 선정
대표적인 오픈 소스 Proxy 서버로는 Squid 가 있다. Apache Httpd Forward Proxy 및 vhost 를 활용하여도 충분히 가능할 것으로 보인다. Httpd 의 본기능은 웹서버이므로 Proxy 서버로 유명한 Squid 를 활용해보고 싶었다. 설정도 간편하고 ACL 설정도 편리해 보였다.
Squid
Proxy 서버 구축
공적으로 함께 활용하는 서버는 기본 경로의 패키지 설치보다, 특정 디렉토리를 생성하여 관련 파일들을 분산되지 않도록 설치하는 편인데 (소스 코드 컴파일 및 바이너리 활용), 서비스 등록 (systemd 관련) 에 대한 추가 설정들을 해줘야 하여 yum 을 활용하여 패키지 설치를 하였다.
# yum을 통한 Squid 설치
$ yum install squid
# systemctl 활용하여 Squid 시작
$ systemctl start squid
# Process 확인 및 결과
$ ps -ef |grep squid
root 4884 1 0 18:02 ? 00:00:00 /usr/sbin/squid -f /etc/squid/squid.conf
squid 4886 4884 1 18:02 ? 00:00:00 (squid-1) -f /etc/squid/squid.conf
squid 4887 4886 0 18:02 ? 00:00:00 (logfile-daemon) /var/log/squid/access.log
root 4889 4823 0 18:02 pts/0 00:00:00 grep --color=auto squid
# Port Listen 확인 및 결과 (3182 포트로 Listen 하는 것을 알 수 있다.)
$ netstat -antp |grep squid
tcp6 0 0 :::3128 :::* LISTEN 4968/(squid-1)
Shell
Ref
Proxy 서버 설정
설치 후 각 종 설정은 '/etc/squid/squid.conf 에서 수행할 수 있다.
# Outbound 요청에 대해 해당 Domain 만 허용하기
# ACL 등록
acl [Alias] dstdomain [Domain]
# White-List 등록
http_access allow [Alias]
http_access deny all
# 설정 예시:
# Outbound 허용할 Domain 에 대한 허용 설정
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
acl customnet dstdomain naver.com
acl customnet dstdomain www.naver.com
http_access allow customnet
http_access deny all
Shell
Ref
서버 내 대상 Proxy 서버 설정
요청을 수행할 서버에서 대상 Proxy 서버를 지정해주어야 웹 요청 수행시 해당 Proxy 서버를 경유할 수 있다. CentOS 계열에서는 아래와 같이 지정할 수 있다.
•
보통 계정/세션 별 설정들을 profile 내 등록하는데
나는 '/etc/profile' 보다는 '/etc/profile.d/custom.sh' 경로에 작성해준다.
http_proxy=http://10.101.16.123:3128
export http_proxy
https_proxy=http://10.101.16.123:3128
export https_proxy
Python
•
설정 기입 후 '$ source /etc/profile' 명령으로 현재 세션에 적용시킨다.
•
Proxy 서버를 경유하는 요청은 http (80), https (443) 포트를 활용한 요청에 대해서만 적용된다.
예를들어 DNS 조회에 활용되는53번 포트로의 요청은 해당 Proxy 서버를 경유하지 않는다.
Ref
테스트
현재 Proxy 서버에서는 'naver.com', 'www.naver.com' 도메인에 대해서만 요청을 허용하도록 설정이 되어있다. 허용된 도메인과 그렇지 않은 도메인으로 테스트를 수행해보자.
1.
'www.naver.com' 요청
•
A 서버
◦
'$ curl -IL www.naver.com' 수행 (Reponse 내용이 많으니 대문자 I 옵션으로 헤더만 보자)
$ curl -IL www.naver.com
HTTP/1.1 302 Found
Server: NWS
Content-Type: text/html
Location: https://www.naver.com/
Date: Fri, 09 Apr 2021 09:47:17 GMT
X-Cache: MISS from ip-10-101-16-123.ap-northeast-2.compute.internal
X-Cache-Lookup: MISS from ip-10-101-16-123.ap-northeast-2.compute.internal:3128
Via: 1.1 ip-10-101-16-123.ap-northeast-2.compute.internal (squid/3.5.20)
Connection: keep-alive
HTTP/1.1 200 Connection established
HTTP/2 200
server: NWS
content-type: text/html; charset=UTF-8
cache-control: no-cache, no-store, must-revalidate
pragma: no-cache
p3p: CP="CAO DSP CURa ADMa TAIa PSAa OUR LAW STP PHY ONL UNI PUR FIN COM NAV INT DEM STA PRE"
x-frame-options: DENY
x-xss-protection: 1; mode=block
strict-transport-security: max-age=63072000; includeSubdomains
referrer-policy: unsafe-url
date: Fri, 09 Apr 2021 09:47:17 GMT
content-length: 0
Shell
◦
요청이 성공하였다.
•
B 서버
◦
tcpdump 명령을 활용하여 특정 Network Interface 로 들어오는 트래픽 요청을 확인해보자
◦
'$ tcpdump -i eth0 src 10.101.31.58' (A 서버 IP 로 src 를 특정해보았다.)
$ tcpdump -i eth0 src 10.101.31.58
18:49:38.889887 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [S], seq 2594265738, win 26883, options [mss 8961,sackOK,TS val 3009468792 ecr 0,nop,wscale 7], length 0
18:49:38.890039 ARP, Reply ip-10-101-31-58.ap-northeast-2.compute.internal is-at 02:5e:40:89:74:ce (oui Unknown), length 28
18:49:38.890396 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 2311765452, win 211, options [nop,nop,TS val 3009468793 ecr 938999942], length 0
18:49:38.890527 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 0:128, ack 1, win 211, options [nop,nop,TS val 3009468793 ecr 938999942], length 128
18:49:38.905755 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 380, win 219, options [nop,nop,TS val 3009468808 ecr 938999958], length 0
18:49:38.906259 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [S], seq 627413643, win 26883, options [mss 8961,sackOK,TS val 3009468809 ecr 0,nop,wscale 7], length 0
18:49:38.906504 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 246092809, win 211, options [nop,nop,TS val 3009468809 ecr 938999959], length 0
18:49:38.906568 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 0:118, ack 1, win 211, options [nop,nop,TS val 3009468809 ecr 938999959], length 118
18:49:38.908398 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 40, win 211, options [nop,nop,TS val 3009468811 ecr 938999961], length 0
18:49:38.914077 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 118:635, ack 40, win 211, options [nop,nop,TS val 3009468817 ecr 938999961], length 517
18:49:38.918625 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 4585, win 339, options [nop,nop,TS val 3009468821 ecr 938999969], length 0
18:49:38.919650 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 635:761, ack 4585, win 339, options [nop,nop,TS val 3009468822 ecr 938999969], length 126
18:49:38.921857 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 761:814, ack 4636, win 339, options [nop,nop,TS val 3009468825 ecr 938999974], length 53
18:49:38.921892 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 814:912, ack 4636, win 339, options [nop,nop,TS val 3009468825 ecr 938999974], length 98
18:49:38.921969 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 912:985, ack 4636, win 339, options [nop,nop,TS val 3009468825 ecr 938999974], length 73
18:49:38.923804 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 985:1023, ack 4704, win 339, options [nop,nop,TS val 3009468826 ecr 938999976], length 38
18:49:38.929386 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 5064, win 403, options [nop,nop,TS val 3009468832 ecr 938999978], length 0
18:49:38.930006 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [F.], seq 128, ack 380, win 219, options [nop,nop,TS val 3009468833 ecr 938999958], length 0
18:49:38.930032 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 1023:1054, ack 5064, win 403, options [nop,nop,TS val 3009468833 ecr 938999978], length 31
18:49:38.930422 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32864 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 381, win 219, options [nop,nop,TS val 3009468833 ecr 938999983], length 0
18:49:38.930727 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [F.], seq 1054, ack 5064, win 403, options [nop,nop,TS val 3009468833 ecr 938999978], length 0
18:49:38.931118 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32866 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 5065, win 403, options [nop,nop,TS val 3009468834 ecr 938999983], length 0
Shell
◦
위와 같이 요청이 들어오는 것을 볼 수 있다.
◦
A 서버에서 대상 Proxy 서버를 지정하지 않으면 트래픽 자체가 발생하지 않는다.
2. 'www.google.co.kr' 요청
•
A 서버
◦
'$ curl -IL www.google.co.kr' 수행
$ curl -IL www.google.co.kr
HTTP/1.1 403 Forbidden
Server: squid/3.5.20
Mime-Version: 1.0
Date: Fri, 09 Apr 2021 09:51:58 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 3606
X-Squid-Error: ERR_ACCESS_DENIED 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from ip-10-101-16-123.ap-northeast-2.compute.internal
X-Cache-Lookup: NONE from ip-10-101-16-123.ap-northeast-2.compute.internal:3128
Via: 1.1 ip-10-101-16-123.ap-northeast-2.compute.internal (squid/3.5.20)
Connection: keep-alive
Shell
◦
요청이 실패하였다. Squid 단에서 403 코드를 반환하며 차단하는 것을 볼 수 있다.
•
B 서버
◦
'$ tcpdump -i eth0 src 10.101.31.58' (A 서버 IP 로 src 를 특정해보았다.)
$ tcpdump -i eth0 src 10.101.31.58
18:51:58.289255 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [S], seq 3408565046, win 26883, options [mss 8961,sackOK,TS val 3009608193 ecr 0,nop,wscale 7], length 0
18:51:58.289505 ARP, Reply ip-10-101-31-58.ap-northeast-2.compute.internal is-at 02:5e:40:89:74:ce (oui Unknown), length 28
18:51:58.289770 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 558208716, win 211, options [nop,nop,TS val 3009608194 ecr 939139344], length 0
18:51:58.289820 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [P.], seq 0:134, ack 1, win 211, options [nop,nop,TS val 3009608194 ecr 939139344], length 134
18:51:58.290460 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 495, win 219, options [nop,nop,TS val 3009608195 ecr 939139345], length 0
18:51:58.290950 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [F.], seq 134, ack 495, win 219, options [nop,nop,TS val 3009608195 ecr 939139345], length 0
18:51:58.291375 IP ip-10-101-31-58.ap-northeast-2.compute.internal.32868 > ip-10-101-16-123.ap-northeast-2.compute.internal.squid: Flags [.], ack 496, win 219, options [nop,nop,TS val 3009608196 ecr 939139345], length 0
Shell
◦
위와 같이 요청이 들어오는 것을 볼 수 있다. 요청에 대한 차단이므로 'www.naver.com' 만큼 통신량이 많지 않아 보인다.
총평
유후! 이렇게 도메인 기반으로 접근 차단하는 방화벽 없이도 Proxy 서버 구축만으로도 Domain 기반 Outbound 관리를 할 수 있게 되었다! 
