squid proxy를 이용하여 ec2 장비에 forward proxy를 만드는 방법에 대해 실습해 보겠습니다. forward proxy란 사용자가 특정 사이트에 직접 접속하는게 아니라 proxy가 대신 사이트에 연결하여 받은 결과를 클라이언트에게 전달하는 것 입니다. forward proxy는 대개 캐슁 기능을 가지고 있어 자주 요청되는 컨텐츠에 대해 빠른 응답속도 및 결과를 얻을 수 있습니다. 또한 보안이 매우 중요한 환경에서 외부와의 통신을 proxy를 통해 제한하는데도 사용할 수 있습니다.

Squid Proxy

http://www.squid-cache.org/

Squid 프록시는 HTTP, HTTPS, FTP 등을 지원하는 웹용 캐싱 프록시입니다. 자주 요청하는 웹 페이지를 캐싱하고 재사용하여 대역폭을 줄이고 응답 시간을 개선할 수 있습니다. Squid는 광범위한 액세스 제어를 제공하며 훌륭한 서버 가속기로 동작할 수 있습니다. Windows를 포함한 대부분의 사용 가능한 운영 체제에서 실행될 수 있어 범용적으로 사용할 수 있습니다.

Proxy 설치를 위한 EC2 생성

squid를 설치할 EC2장비를 생성합니다.

EC2 – Launch Instance – Amazon Linux 2 AMI (HVM) select

  • Choose an Instance Type
    • t2.micro
  • Configure Instance Details
    • Network : 생성할 VPC 선택
    • Subnet : private 망에서만 사용할 것이면 private subnet을 공용으로 사용할 것이면 public subnet을 선택. 실습에서는 public subnet으로 세팅
    • Auto-assign Public IP : Enable
  • Add Tags
    • Key : Name / Value : Proxy1
  • Configure Security Group
    • Create a new security group
    • Security group name : proxy-sg
    • Add Rule
      • Squid 서버에 접속할 수 있도록 아래 정보로 Security Group을 생성합니다. 서비스에 사용시엔 보안을 위해 proxy default port를 변경하고, Source의 경우도 필요한 대역으로 한정하여 생성하는 것이 좋습니다.
      • Port Range : 3128
      • Source : 0.0.0.0/0
  • Review Instance Launch
    • Launch를 클릭하고 장비 접속시 필요한 key pair를 세팅한 후에 Launch Instances를 클릭하여 EC2 장비를 생성합니다.

EC2에 Squid Proxy 설치

yum 으로 설치

$ ssh -i ssh-key파일.pem ec2-user@ec2-public-ip-address
$ sudo yum install squid -y 

source compile로 설치

http://www.squid-cache.org/Versions/에서 stable 버전을 다운받아 설치합니다.

$ wget http://www.squid-cache.org/Versions/v4/squid-4.16.tar.gz
$ tar xvfz squid-4.16.tar.gz
$ cd squid-4.16/
$ ./configure --prefix=설치위치
$ make
$ make install

config 수정

/etc/squid/squid.conf 내용을 필요에 따라 수정합니다.

/etc/squid/squid.conf를 열어보면 제일 상단에 proxy에 접근할 수 있는 소스 네트워크 목록이 보입니다. 여기에 속해있는 ip대역만이 squid proxy에 요청을 보낼 수 있습니다. 기본 설정은 aws내에서 사용할 수 있는 3가지 CIDR(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) 대역이 세팅되어 있습니다.

acl localnet src 10.0.0.0/8    # RFC1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/16        # RFC1918 possible internal network
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines

만약 위의 ip 대역이 아닌곳에서 접근이 필요하면 다음과 같이 src(source) 대역을 추가하고 squid를 재시작하면 됩니다.

# 설정파일을 열고 acl localnet 항목을 하나 추가한다.
$ vi squid.conf
acl localnet src 접근_IP_CIDR 대역
# 설정을 적용한다.
$ sudo systemctl restart squid

Squid 시작/활성화

$ sudo systemctl start squid
$ sudo systemctl enable squid
# 상태 확인
$ sudo systemctl status squid
 squid.service - Squid caching proxy
   Loaded: loaded (/usr/lib/systemd/system/squid.service; enabled; vendor preset: disabled)
   Active: active (running) since 화 2021-06-22 09:46:57 UTC; 12min ago
  Process: 2079 ExecStart=/usr/sbin/squid $SQUID_OPTS -f $SQUID_CONF (code=exited, status=0/SUCCESS)
  Process: 2073 ExecStartPre=/usr/libexec/squid/cache_swap.sh (code=exited, status=0/SUCCESS)
 Main PID: 2106 (squid)
   CGroup: /system.slice/squid.service
           ├─2106 /usr/sbin/squid -f /etc/squid/squid.conf
           └─2109 (squid-1) -f /etc/squid/squid.conf

 6월 22 09:46:57 ip-10-235-16-114.ap-northeast-2.compute.internal systemd[1]: Starting Squid caching proxy...
 6월 22 09:46:57 ip-10-235-16-114.ap-northeast-2.compute.internal squid[2106]: Squid Parent: will start 1 kids
 6월 22 09:46:57 ip-10-235-16-114.ap-northeast-2.compute.internal systemd[1]: Started Squid caching proxy.
 6월 22 09:46:57 ip-10-235-16-114.ap-northeast-2.compute.internal squid[2106]: Squid Parent: (squid-1) process 2109 started
Hint: Some lines were ellipsized, use -l to show in full.

Proxy 테스트

해당 장비에 접속하여 특정 사이트의 정보를 요청하면 결과를 받을 수 있습니다.

$ curl -x localhost:3128 https://www.google.com
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ko"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/logos/doodles/2021/get-vaccinated-wear-a-mask-save-lives-june-22-6753651837109280-law.gif" itemprop="image"><meta content="&#44032;&#44620;&#50868; &#53076;&#47196;&#45208;19 &#48177;&#49888; &#51217;&#51333;&#49548;&#47484; &#54869;&#51064;&#54616;&#49464;&#50836;" property="twitter:title"><meta content="&#44032;&#44620;&#50868; &#53076;&#47196;&#45208;19 &#48177;&#49888; &#51217;&#51333;&#49548;&#47484; &#54869;&#51064;&#54616;&#49464;&#50836;. #GoogleDoodle" property="twitter:description"><meta content="&#44032;&#44620;&#50868; &#53076;&#47196;&#45208;19 &#48177;&#49888; &#51217;&#51333;&#49548;&#47484; &#54869;&#51064;&#54616;&#49464;&#50836;. #GoogleDoodle" property="og:description"><meta content="summary_large_image" property="twitter:card"><meta content="@GoogleDoodles" property="twitter:site"><meta content="https://www.google.com/logos/doodles/2021/get-vaccinated-wear-a-mask-save-lives-june-22-6753651837109280-2xa.gif" property="twitter:image"><meta content="https://www.google.com/logos/doodles/2021/get-vaccinated-wear-a-mask-save-lives-june-22-6753651837109280-2xa.gif" property="og:image"><meta content="1000" property="og:image:width"><meta content="400" property="og:image:height"><meta content="https://www.google.com/logos/doodles/2021/get-vaccinated-wear-a-mask-save-lives-june-22-6753651837109280-2xa.gif" property="og:url"><meta content="video.other" property="og:type"><title>Google</title><script nonce="y74VleE93FhDVzSGp6dx6w==">(function()

Proxy 접속 로그 확인

/var/log/squid 하위에서 접속 로그를 확인할 수 있습니다.

$ sudo tail -f /var/log/squid/access.log
2021/07/28 06:09:48 127.0.0.1 TCP_MISS/200:HIER_DIRECT "CONNECT www.google.com:443 HTTP/1.1" 200 3824 "curl/7.61.1" "-"

EC2 이미지 생성

동일한 설정의 Squid 장비를 여러대 생성해야 할때 이미 설치된 EC2를 활용할 수 있도록 이미지를 생성해 둡니다.

  • EC2 – proxy-1 체크
  • Actions – Image and templates – Create Image – 각 항목에 적당한 내용 입력 후 Create Image를 클릭하여 이미지 생성

생성이 완료되면 EC2 – Images – AMIs에서 확인할 수 있습니다.

EC2 이미지로 추가 Proxy 생성

EC2 – Images – AMIs에 접속하여 생성된 이미지를 확인하고 proxy-image를 체크한 후 Launch를 클릭합니다. 위에서 첫번째 Proxy를 생성할때와 유사한 화면이 노출되며 적절하게 내용을 작성한 후 Launch Instance를 클릭하여 새로운 EC2 인스턴스를 생성합니다. 최초 생성시와 다른 점은 이미지를 적용하였기 때문에 Squid Proxy가 설치된 상태로 EC2가 생성된다는 점입니다.

장비에 접속하여 테스트를 해보면 Proxy기능이 작동하는 것을 확인 할 수 있습니다.

# 두번째 장비 접속
$ ssh -i ssh-key파일.pem ec2-user@두번째장비ec2-public-ip-address
# Proxy 테스트
$ curl -x localhost:3128 https://www.google.com

LoadBalancer 적용

여러대의 proxy 서버를 단일 endpoint로 사용하기 위해 LoadBalancer를 생성합니다. Network LoadBalancer를 다음과 같이 생성합니다.

  • EC2 – Load Balancers – Create Load Balancer – Network Load Balancer – Create
  • LoadBalancerName : squid-proxy
    Scheme : Internet-facing 선택
    VPC : default
    Mappings : az선택 후 public subnet 선택
  • Listener and Routing
    Port : 3128
    forward to – Create Target Group를 선택
  • Target Group – 로드 밸런싱할 EC2서버의 집합
    • 위에서 생성한 두개의 squid ec2 Instance선택하여 타겟 그룹을 생성합니다.
    • TargetGroupName : squid-taget-group
    • Port : 3128 입력 후 Next
    • Available Instances에서 위에서 생성한 squid-proxy-1,2 ec2를 선택 후 Ports for the selected instances에 3128 port를 입력.
    • Include as pending below 클릭하여 서버를 추가하고 Create target group 클릭하여 Target Group 생성을 완료합니다.
  • Target Group을 로드 밸런서에 적용
    • LoadBalancer 설정 화면으로 돌아와 Listener – Forward to 리스트 갱신 후 위에서 생성한 Target Group을 지정합니다.
    • Create load balancer를 눌러 로드밸런서를 생성 합니다. 생성이 완료되면 상태가 Provisioning -> Active로 변경됩니다.
  • security_group inbound rule 추가
    • 만약 squid 서버의 security_group 설정이 기본적으로 inbound에 대해서 모두 막혀 있을경우엔 로드밸런서가 squid 서버에 접근할 수 있도록 squid서버의 security_group – inbound rule에 로드밸런서 VPC의 CIDR에 대해서 3128 port를 개방해야 합니다. 실습에서는 proxy-sg를 생성시 모든 IP(0.0.0.0) 대역에 대해서 3128 port를 개방했으므로 따로 처리할 필요는 없습니다.

LoadBalancer 테스트

로드 밸런서의 DNS name으로 proxy설정을 한 후 정상 작동하는지 확인합니다.

$ curl -x squid-proxy-99815861995ce0b2.elb.ap-northeast-2.amazonaws.com:3128 https://www.google.com
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ko"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="TG5k+YhFbwFNjTkkWSjSDQ==">(function(){window.google={kEI:'5P0AYb2tOdeK-Aa5wI3gBQ',kEXPI:'0,772215,1,530320,56873,954,5104,207,4804,2316,383,246,5,1354,5251,1122515,1197727,556,88,328896,51223,16115,28684,17572,4859,1361,9290,3025,4749,7994,4841,4020,978,13228,2676,1171,4192,6430,7432,7096,4516,2778,919,910,4171,1593,1279,2212,531,148,1943,6297,3514,606,2023,1777,520,14670,605,2622,2845,7,4774,7580,5096,7876,5037,3407,908,2,941,2614,3783,9359,3,346,230,6459,149,13975,4,1528,2304,1236,5226,577,4683,2015,4067,14308,2658,4242,2459,654,32,13628,2305,638,1494,5586,10535,665,2521,3273,2563,4094,18,2239,881,6,908,3,3541,1,14263,447,1814,283,912,5992,12526,2,1394,2806,1715,2,3057,2538,2,1,3,3623,4798,619,1312,1532,2379,1804,618,1274,4578,2051,1646,172,5552,2,1040,1160,1269,17,3409,2,399,1311,292,177,2022,182,2719,4545,3,123,4607,743,13,1448,86,3088,585,463,2538,2,6,2299,119,1037,1353,6,125,593,305,1510,426,554,57,1163,18,140,190,566,2,322,93,833,288,74,214,53,1055,330,1251,1598,1468,74,2062,528,1089,521,696,592,363,1615,351,1,146,76,2,4,913,6,159,228,1655,11,6,5602310,3904,190,36,220,59,1,5996809,153,2800543,882,444,1,2,80,1,1796,1,9,2,2551,1,748,141,795,563,1,4265,1,1,2,1331,3299,843,2609,155,17,13,72,139,4,2,20,2,169,13,19,46,5,39,96,548,29,2,2,1,2,1,2,2,7,4,1,2,2,2,2,2,2,353,513,186,1,1,158,3,2,2,2,2,2,4,2,3,3,235,34,10,40,17,15,11,8,23654757,299865,2867253,1171784,7,2307,338,3,1454,960,1074,5,1707',kBL:'hWJ9'};google.sn='webhp';google.kHL='ko';})();(function(){
var f=this||self;var h,k=[];function l(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||h}function m(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("leid")));)a=a.parentNode;return b}
function n(a,b,c,d,g){var e="";c||-1!==b.search("&ei=")||(e="&ei="+l(d),-1===b.search("&lei=")&&(d=m(d))&&(e+="&lei="+d));d="";!c&&f._cshid&&-1===b.search("&cshid=")&&"slh"!==a&&(d="&cshid="+f._cshid);c=c||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+e+"&zx="+Date.now()+d;/^http:/i.test(c)&&"https:"===window.location.protocol&&(google.ml&&google.ml(Error("a"),!1,{src:c,glmm:1}),c="");

Proxy 증설

Proxy를 사용하는 서비스가 많아 현재 장비로 트래픽을 감당하기 힘들 경우엔 위에서 생성한 EC2 이미지로 Proxy 서버를 추가로 생성한 다음 로드밸런서 TargetGroup에 추가하여 처리량을 확장할 수 있습니다.

기타 추가 설정

Version 정보 노출 숨기기

Server version
응답헤더를 통한 버전정보가 노출되지 않도록 설정 합니다.

Via version
프록시에서만 사용되는 헤더로 요청 / 응답시 사용됨에 따라, 버전정보가 노출되지 않도록 설정 합니다.

$ vi /etc/squid/squid.conf

# via version off via off
# Server version off 
httpd_suppress_version_string on 
reply_header_access Server deny all
# Cache version off
reply_header_access X-Cache deny all reply_header_access X-Cache-Lookup deny all

Error Page
기본 Error Page시 사용시 Footer를 통한 버전정보가 노출되지 않도록 설정 합니다. Error page template 위치 확인 후 아래와 같이 실행 합니다.
기본 위치 : /usr/share/squid/errors

$ sudo -i grep -rli "Generated %T by %h (%s)" /usr/share/squid/errors/ | sudo -i xargs sed -i 's/Generated %T by %h (%s)/./g'

LogFormat 설정

기본 로그 포맷을 보기 편한 형태로 설정합니다.
http://www.squid-cache.org/Doc/config/logformat/

$ vi /etc/squid/squid.conf
logformat customformat %{%Y/%m/%d %H:%M:%S}tl %>a %Ss/%03>Hs:%Sh "%rm %ru HTTP/%rv" %>Hs %<st "%{User-Agent}>h" "%{Referer}>h" access_log /var/log/squid/access.log customformat

ACL 설정

출발지(src)를 내부서버 대역이나 특정 IP로 제한하여 proxy에 요청하는 클라이언트를 제한 할 수 있습니다. 또한 목적지(dst)를 제한하여 proxy가 요청할 수 있는 목적지 사이트도 제한할 수 있습니다.

$ vi /etc/squid/squid.conf
acl SSL_ports port 443
acl Safe_ports port 80 8080

# Method Setting
acl Safe_methods method GET POST PUT OPTIONS CONNECT

http_access deny !Safe_ports

http_access allow localhost manager
http_access deny manager

include /etc/squid/in-outbound-acl.conf

// 나머지 설정 생략

in-outbound-acl.conf

# proxy에 접근할 수 있는 아이피 대역 설정- server
acl src_service_vpc src 10.249.0.0/18

# proxy에 접근할 수 있는 아이피 대역 설정 - office
acl src_office src 203.123.171.170/32

# proxy에서 요청할 수 있는 destination 도메인 설정
acl dst_google dstdomain www.google.com
acl dst_naver dstdomain www.naver.com

http_access allow Safe_methods src_service_vpc dst_google
http_access allow Safe_methods src_office dst_google
http_access allow Safe_methods src_service_vpc dst_naver
http_access allow Safe_methods src_office dst_naver