본문 바로가기
[AWS 기타]

Squid로 NAT 인스턴스에 DNS 필터링을 추가하는 방법

by SAMSUNG Metaverse-Cloud 2023. 1. 19.
728x90

 

 

고객이 아웃바운드 통신을 제어하고 싶다는 요구사항이 있다.
이럴때의 해결 방법에대하여 검색하니 Squid라는 proxy를 이용하여 NAT Instance처럼 사용하는 방법이 있었다.

 

Amazon VPC (Virtual Private Cloud)를 사용하면 사용자가 정의한 가상 사설 망에서 AWS 리소스를 시작할 수 있다. Amazon VPC에서 NAT 인스턴스와 NAT 게이트웨이를 이용하여 아웃바운드 트래픽을 허용한다.

보안 및 컴플라이언스를 위해 이러한 인스턴스에서 시작한 요청을 필터링해야 할 수 있다. iptables 규칙을 사용하면 사전 정의 된 대상 포트 또는 IP 주소를 기반으로 NAT 인스턴스로 아웃 바운드 트래픽을 제한 할 수 있다. 그러나 iptables 규칙을 사용하여 쉽게 달성 할 수없는 AWS 엔드 포인트에만 요청을 허용하는 것과 같이 더 복잡한 정책을 시행해야 할 수도 있다.

오픈 소스 프록시 인 Squid가 HTTP 및 HTTPS 아웃 바운드 트래픽을 지정된 인터넷 도메인 집합으로 제한하는 동시에 개인 서브넷의 인스턴스를 완전히 투명하게 처리 할 수있는 방법에 대해 설명하고 제공한다. 먼저이 접근법에 필요한 인프라 자원을 만드는 방법을 간략하게 설명한다. 그런 다음 Squid Proxy를 설치, 구성 및 테스트하는 단계별 지침을 안내한다.

가능한 대안 솔루션은 Amazon VPC에 프록시 (포워드 프록시라고도 함)를 배포하는 것일 수 있다. 그러나 중요한 단점은 프록시가 개인 서브넷의 모든 인스턴스에 대해 명시 적으로 구성되어야 한다. 이로 인해 응용 프로그램이 프록시 사용을 지원하지 않는 경우 해결하기가 어렵지 않더라도 문제를 해결하기 어려울 수있는 연결 문제가 발생할 수 있다.

설정 방법

다음 단계는 필수 자원을 수동으로 작성하고 구성하는 단계다. 또는 AWS CloudFormation을 사용하여이 절차를 자동화 할 수 있다. 스택 생성을 클릭하여 CloudFormation 콘솔을 열고 내가 개발 한 템플릿에서 AWS CloudFormation 스택을 만든다. 화면의 지침을 따르고 스택 작성이 완료되면이 블로그 게시물의 뒷부분에있는 "배치 테스트"섹션으로 직접 이동 (최대 20 분이 소요될 수 있음).

참고 : VPC와 동일한 지역의 S3 버킷에 요청을 허용해야하는 경우 Amazon S3에 VPC 종점을 대신 사용할 수 있다 (VPC 종점 참조). 이를 통해 인터넷을 통한 액세스없이 VPC와 다른 AWS 서비스 사이에 개인 연결을 만들 수 있다. 또한 Amazon S3 자원에 액세스하기위한 엔드 포인트 사용을 제어하는 정책이 있다.

VPC와 2개의 EC2 설정

다음 단계에서는 VPC 및 두 개의 EC2 인스턴스를 수동으로 만들고 구성하는 과정 이다. 하나는 Squid 배포를위한 공용 서브넷에, 다른 하나는 구성 테스트를위한 개인 서브넷에 있다. 전제 조건이 유사하기 때문에 자세한 내용은 NAT 인스턴스 설명서를 참조.
 
 
VPC 및 2개의 EC2 instance를 생성하려면 : 
  1. VPC를 생성한다. (도움이 필요하면 VPC생성 참고).
  2. 2개의 subnet을 생성한다. (Creating a Subnet 참고): 하나는 “Public Subnet” 그리고 다른 하나는and “Private Subnet.”으로 생성.
  3. Internet Gateway를 생성하고 위에 생성한 VPC에 attach 한다. (Attaching an Internet Gateway 참고).
  4. VPC (0.0.0.0/0)  외부로 향하는 트래픽을 인터넷 게이트웨이로 보내는 규칙을 기본 경로 테이블에 추가한다.(Route Table에서 route 추가 및 제거 참조).
  5. VPC default security group에 SSH traffic (TCP 22) 접속 아이피를 규칙에 추가한다. (Security Group에  규칙 추가 참조).
  6. Public Subnet에 "Squid Instance"라는 Amazon Linux t2.micro instance를 시작한다. (NAT instance AMI가 아니라, Amazon Linux AMI를 사용해야 한다). Auto-assign Public IP를 활성화 한다, choose the VPC에  기본 security group을 설정하고, 유효한 key pair파일을 선택한다. 다른 모든 파라미터는 기본값으로 설정한다. (Launching an Instance 참조).
  7. 인스턴스가 실행되기 시작하면 소스 / 대상 확인을 비활성화한다.  (Disable Source/Destination Checks 참고).
  8. VPC에 새 route table을 만듭니다. VPC (0.0.0.0/0)외부로 향하는 트래픽을 Squid 인스턴스에 보내고, 이 새 route table을 Private Subnet과 연결하는 규칙을 추가 한다.
  9. “Testing Instance Role” 라는 인스턴스 역할을 만들고 관리되는 정책 AmazonEC2ReadOnlyAccess를 첨부한다. (detailed instructions).
  10. 마지막으로 Private Subnet에서 "Testing Instance"라는 또 다른 Amazon Linux t2.micro 인스턴스를 시작한다 (NAT 인스턴스 AMI가 아니라 Amazon Linux AMI를 사용해야한다). 인스턴스 역할로 인스턴스 역할 테스트를 선택하고 VPC에  기본 security group을 설정하고, 유효한 key pair파일을 선택한다. 다른 모든 파라미터는 기본값으로 설정한다.

다음 다이어그램은이 프로세스의 구성 요소가 서로 상호 작용하는 방법을 보여준다. Squid 인스턴스는 테스트 인스턴스가 보낸 HTTP / HTTPS 요청을 가로 챈다. 그런 다음 Squid 인스턴스는 인터넷 게이트웨이를 통과하는 테스트 인스턴스를 대신하여 대상 호스트와의 연결을 시작한다.

 



Squid 설치

Squid는 필터링 정책이 적용되기 전에 요청된 도메인을 차단한다. 
  • HTTP의 경우 Squid는 요청되는 인터넷 호스트를 지정하는 모든 HTTP / 1.1 요청 메시지에 포함 된 Host 헤더 필드를 검색한다.
  • HTTPS의 경우 HTTP 트래픽은 개인 서브넷의 인스턴스와 원격 호스트 사이의 TLS 연결에 캡슐화 된다. Squid는 헤더가 암호화되어 있으므로 Host 헤더 필드를 검색 할 수 없다. SslBump라는 기능은 Squid가 트래픽을 해독하도록 허용하지만 대부분의 경우 인증서가 유효하지 않은 것으로 간주되어 클라이언트에게는 투명하지 않다.  대신 SslPeekAndSplice라고하는 기능을 사용하여 요청한 인터넷 호스트가 포함 된 TLS 초기화에서 서버 이름 표시 (SNI)를 검색 한다.결과적으로 Squid는 HTTPS 트래픽의 암호를 해독하지 않고도 필터링을 결정할 수 있습니다.
참고 : 일부 오래된 클라이언트 측 소프트웨어 인 스택은 SNI를 지원하지 않는다. 다음은 SNI를 지원하는 중요한 스택 및 프로그래밍 언어의 최소 버전 이다 : Python 2.7.9 및 3.2, Java 7 JSSE, wget 1.14, OpenSSL 0.9.8j, cURL 7.18.1SslPeekAndSplice 기능은 Squid 3.5에 도입되었다. 그러나 이 글이 작성되었을 때 Amazon Linux 저장소에는 Squid 3.1.10이 포함되어 있다 (Squid 3.5가 yum info squid 명령을 사용하여 사용 가능한지 확인할 수 있음). 이 게시물의 목적을 위해 공식 소스 코드에서 Squid 3.5를 컴파일하고 설치한다.
참고 :이 Squid 설치에는이 예제에 필요한 최소 기능이 포함되어 있으며 프로덕션 용도로는 사용되지 않습니다. 자신의 필요에 맞게 수정하고 자신의 Red Hat Package Manager (RPM) package 또는 비공식 RPM packages for CentOS 6 Squid를 설치할 수 있다.
 

Squid 설치
Squid 인스턴스에서 Squid를 수동으로 컴파일, 설치 및 구성하려면:

  1. Squid instance에 SSH를 이용하여 ec2-user 로 접속한다.
  2. 필수 구성요소 package들을 설치.
sudo yum update -y
sudo yum install -y perl gcc autoconf automake make sudo wget gcc-c++    libxml2-devel libcap-devel libtool libtool-ltdl-devel openssl openssl-devel
  1.  Squid page로 이동하여 최신 릴리스 (이 게시물이 작성된 마지막 릴리스 인 3.5.13)의 tar.gz 소스 코드 아카이브에 대한 링크를 검색하라. 이 링크를 사용하여 Squid 인스턴스에서 아카이브를 다운로드하고 압축을 푼다.
SQUID_ARCHIVE=http://www.squid-cache.org/Versions/v3/3.5/squid-3.5.13.tar.gz
cd /tmp
wget $SQUID_ARCHIVE
tar xvf squid*.tar.gz
cd $(basename squid*.tar.gz .tar.gz)
  1. 최소 설치 옵션으로 Squid 를 설치한다. 최대 15분이 소요될수 있다.
sudo ./configure --prefix=/usr --exec-prefix=/usr --libexecdir=/usr/lib64/squid --sysconfdir=/etc/squid --sharedstatedir=/var/lib --localstatedir=/var --libdir=/usr/lib64 --datadir=/usr/share/squid --with-logdir=/var/log/squid --with-pidfile=/var/run/squid.pid --with-default-user=squid --disable-dependency-tracking --enable-linux-netfilter --with-openssl --without-nettle

sudo make
sudo make install
  1. Squid 설치를 완료한다.
sudo adduser -M squid
sudo chown -R squid:squid /var/log/squid /var/cache/squid
sudo chmod 750 /var/log/squid /var/cache/squid
sudo touch /etc/squid/squid.conf
sudo chown -R root:squid /etc/squid/squid.conf
sudo chmod 640 /etc/squid/squid.conf
cat | sudo tee /etc/init.d/squid <<'EOF'
#!/bin/sh
# chkconfig: - 90 25
echo -n 'Squid service'
case "$1" in
start)
/usr/sbin/squid
;;
stop)
/usr/sbin/squid -k shutdown
;;
reload)
/usr/sbin/squid -k reconfigure
;;
*)
echo "Usage: `basename $0` {start|stop|reload}"
;;
esac
EOF
sudo chmod +x /etc/init.d/squid
sudo chkconfig squid on
참고 : RPM 패키지에서 Squid를 설치 한 경우 Squid 인스턴스에 이미 필요한 구성이 있으므로 다음 단계를 진행하기 전에 Squid 설치에 대한 이전 지침을 따르지 않아도 된다.

Squid 시작과 구성

TSslPeekAndSplice 기능은 SslBump와 동일한 Squid 모듈에 구현 된다. 이 모듈을 사용하려면 Squid가 인증서를 제공해야하지만 HTTPS 트래픽을 디코딩하는 데는 사용되지 않는다. OpenSSL을 사용하여 인증서를 만든다.
sudo mkdir /etc/squid/ssl
cd /etc/squid/ssl
sudo openssl genrsa -out squid.key 2048
sudo openssl req -new -key squid.key -out squid.csr -subj "/C=XX/ST=XX/L=squid/O=squid/CN=squid"
sudo openssl x509 -req -days 3650 -in squid.csr -signkey squid.key -out squid.crt
sudo cat squid.key squid.crt | sudo tee squid.pem
그런 다음 AWS 종단점에 해당하는 *.amazonaws.com에 대한 요청을 허용하도록 Squid를 구성한다.정의 된 AWS 서비스 집합에만 액세스를 제한 할 수 있다. EndPoint의 자세한 목록은 AWS Regions 과 Endpoints를 참고.
HTTPS traffic의 경우 Squid에게 "peek"(SNI 검색)을 지시 한 다음 "splice"(디코딩없이 TCP 터널이 됨) 또는 요청 된 호스트에 따라 연결을 "종료"하도록 지시하는 ssl_bump 지시문에 유의해야 한다.
cat | sudo tee /etc/squid/squid.conf <<EOF
visible_hostname squid

#Handling HTTP requests
http_port 3129 intercept
acl allowed_http_sites dstdomain .amazonaws.com
#acl allowed_http_sites dstdomain [you can add other domains to permit]
http_access allow allowed_http_sites

#Handling HTTPS requests
https_port 3130 cert=/etc/squid/ssl/squid.pem ssl-bump intercept
acl SSL_port port 443
http_access allow SSL_port
acl allowed_https_sites ssl::server_name .amazonaws.com
#acl allowed_https_sites ssl::server_name [you can add other domains to permit]
acl step1 at_step SslBump1
acl step2 at_step SslBump2
acl step3 at_step SslBump3
ssl_bump peek step1 all
ssl_bump peek step2 allowed_https_sites
ssl_bump splice step3 allowed_https_sites
ssl_bump terminate step2 all

http_access deny all
EOF
Squid 는 포트 3129에서 HTTP 트래픽을 수신하고 HTTPS에서 3130을 수신한다. Squid는 80과 443을 직접들을 수 없기 때문에 iptables을 사용하여 private subnet의 인스턴스에서 들어오는 요청을 Squid 포트로 redirect 해야 한다. 표준 NAT 인스턴스처럼 IP 전달을 활성화하거나 앞으로 규칙을 추가 할 필요가 없다.
 
Squid는 포트 3129에서 HTTP 트래픽을 수신하고 HTTPS에서 3130을 수신합니다. Squid는 80과 443을 직접들을 수 없기 때문에 iptables를 사용하여 개인 서브넷의 인스턴스에서 들어오는 요청을 Squid 포트로 리디렉션 해야합니다. 표준 NAT 인스턴스처럼 IP 전달을 활성화하거나 앞으로 규칙을 추가 할 필요가 없습니다.
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3129
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 3130
sudo service iptables save
Squid를 실행한다.
sudo service squid start

배포 테스트

이전에 시작된 테스트 인스턴스를 사용하여 구성을 테스트 할 수 있다. 이 인스턴스는 인터넷에서 액세스 할 수 없으므로 Squid 인스턴스로 이동하여 테스팅 인스턴스에 로그온 해야한다.
 
두 인스턴스가 같은 키 쌍으로 시작되었으므로 SSH 키를 테스트 인스턴스로 전달하기 위해 -A 인수를 사용하여 Squid 인스턴스에 연결할 수 있다.
ssh-add [key]
ssh -A ec2-user@[public IP of the Squid instance] –i [key]
ssh ec2-user@[private IP of the client instance] –i [key]
다음 명령을 사용하여 proxy instance를 테스트 할 수 있다. Squid는 *.amazonaws.com만 트래픽을 허용하므로 마지막 세개의 요청만 유효한 응답을 반환해야 한다.
 
curl http://www.amazon.com
curl https://www.amazon.com
curl http://calculator.s3.amazonaws.com/index.html
curl https://calculator.s3.amazonaws.com/index.html
aws ec2 describe-regions --region us-east-1
 

이제 squid를 이용하여 아웃바운드를 제어할 수 있다.





참조 : AWS blog https://aws.amazon.com/ko/blogs/security/how-to-add-dns-filtering-to-your-nat-instance-with-squid/

 

 

https://frompmtoawssa.blogspot.com/2018/03/squid-nat-dns.html

 

728x90