squid proxy를 이용하여 ec2 장비에 forward proxy를 만드는 방법에 대해 실습해 보겠습니다. forward proxy란 사용자가 특정 사이트에 직접 접속하는게 아니라 proxy가 대신 사이트에 연결하여 받은 결과를 클라이언트에게 전달하는 것 입니다. forward proxy는 대개 캐슁 기능을 가지고 있어 자주 요청되는 컨텐츠에 대해 빠른 응답속도 및 결과를 얻을 수 있습니다. 또한 보안이 매우 중요한 환경에서 외부와의 통신을 proxy를 통해 제한하는데도 사용할 수 있습니다.
Squid Proxy
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="가까운 코로나19 백신 접종소를 확인하세요" property="twitter:title"><meta content="가까운 코로나19 백신 접종소를 확인하세요. #GoogleDoodle" property="twitter:description"><meta content="가까운 코로나19 백신 접종소를 확인하세요. #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