우리는 인터넷 환경에서 다양한 경우에 Proxy를 사용한다. 보안상의 이유이거나 성능적 이슈에서나 아니면 약간의 불법적인 이유에서 우리는 Proxy를 사용한다.
오늘 이야기할 부분은 크롤링 과정에서 서버 아이피가 차단되었을 때 Proxy 서버를 구성하여 우회하는 방법을 이야기하고자 한다. 약간 불법적인 면이 있으니 사용 유무는 사용자가 알아서 판단해야 한다. 다만 개인적인 목적으로 자동화 툴을 사용하거나, 약간?의 정보 수집 목적으로 사용하는 경우 개인적 생각에 문제가 없지 않을까 한다.
Squid
이번에 사용한 Proxy 서버는 Squid(http://www.squid-cache.org/) 이다. 아래 공식 홈페이지에도 나와있듯이 Proxy 캐시 서버이다. 우리가 원하는 기능은 항상 최신 페이지*를 *차단된 클라이언트 대신 요청하고 전달해 줄 Proxy 서버이지 Cache 서버가 아니다. 크롤링 과정에서 이미 크롤링한 기존 페이지가 다시 크롤링되면 크롤링하는 의미가 없어진다.
What is Squid?
Squid is a fully-featured HTTP/1.0 proxy which is almost (but not quite - we’re getting there!) a fully-featured HTTP/1.1 proxy. Squid offers a rich access control, authorization and logging environment to develop web proxy and content serving applications. Squid offers a rich set of traffic optimization options, most of which are enabled by default for simpler installation and high performance.
…
Why should I deploy Squid?
(Or.. “Why should I bother with web caching? Can’t I just buy more bandwidth?”)
The developers of the HTTP protocol identified early on that there was going to be exponential growth in content and, concerned with distribution mechanisms, added powerful caching primitives
…
하지만 설치 및 구성이 쉽고 성능도 우수하고 캐시 기능을 끌 수 있는 옵션도 있기에 문제가 되지 않아 Squid를 사용하기로 했다.
추가로 아래 기능도 지원하기에 해당 솔루션을 선택했다.
- 불특정 IP 대역에서 요청을 했을때 요청 제한을 할 수 있는가(AWS Lambda에서 크롤링 진행 중, VPC 미 설정)?
- htpassword 기능 지원
- outbound 도메인 제한
- 특정 패턴으로 차단 가능
- 클라이언트 사이드에서 요청 시 별다른 설정이나 구성이 필요 없는가?
- python requests package에서 별다른 추가 작업 없이 바로 사용 가능.
Squid 설치
- 서버 설치는 기본 Red Hat 계열 리눅스를 베이스로 진행 내용입니다.
RPM 설치
Squid 설치하는 방법은 다른 오픈소스 솔루션과 유사하게 컴파일해서 별도로 설치하거나 패키지로 설치하는 방법이 있다. 지금 Proxy 서버를 사용하는 목적상 Proxy 서버가 차단될 경우 바른 다른 서버를 세팅해야 하기에 패키지 설치를 선택했다. 기능상으로도 기본 기능만 사용할 것이기에 특정 옵션을 활성화하기 위한 컴파일 과정에서 필요 없다. 이에 패키지 설치를 진행하였다. 논외로 이후에 다시 언급하겠지만 별도의 기능상에 이유로 컴파일 필요한 부분이 존재하긴한다. 필요 시 선택해서 사용하자.
1 | > sudo yum install squid |
데몬 재시작을 원하면 아래 명령으로 재시작하면 된다.
1 | > sudo systemctl restart squid |
설치가 완료되고 아래 명령으로 데몬의 상태와 로그를 확인할 수 있다. 정상적으로 데몬이 시작된 것을 확인할 수 있다.
1 | > systemctl status squid |
/var/log/message
1 | 4월 18 16:47:10 gcloud-seoul-b574f08e6762de6cd29c7508e28a29e6 systemd[1]: Starting Squid caching proxy... |
추가로 htpasswd 인증을 위해서 아래 패키지를 설치하자.
1 | > yum install httpd-tools |
설정
기본 설정 파일
RPM 패키지로 설치했을 경우 아래 경로에 기본 설정 파일이 존재한다.
/etc/squid
1 | -rw-r----- 1 root squid 1734 4월 18 16:47 squid.conf |
우리가 필요한 파일은 위 파일이다.
squid.conf 파일을 수정하자.
1 |
|
설정 파일 자체가 복잡하지 않다. 기본적으로 오픈할 정책을 정의하고 전체 차단하는 구조이다.
1 | http_access allow 허용 항목 |
지금 사용할 서버는 크롤링 목적으로 https 요청만 포워딩할 것이기에 다른 서비스는 전체 제거했고, IP 역시 요청 클라이언트가 AWS Lambda로 국한됨으로 IP를 한정할 수 없어 모두 오픈했다. 세부적으로 IP 대역으로 오픈할 수 도 있으니 본인에 맞게 설정하길 바란다.
HTTPS용 인증서 생성 및 세팅
신경써야하는 부분은 기본적으로 사용할 기능이 HTTPS 요청을 포워딩 하는 것이기에 Proxy 서버가 인증서를 가지고 있어야한다. 요청 자체가 HTTPS로 진행하기때문에 당연한 이야기이다. 사설 인증서를 하나 만들어서 넣어주자.
1 | > cd /etc/squid |
- 인증서 생성 시 만료일자는 본인에 맞게 넣자.
그리고 설정 파일에 나와 있듯이 인증서 경로를 지정해주면 된다.
1 | https_port 13128 cert=/etc/squid/ssl/squid.crt key=/etc/squid/ssl/squid.key |
htpasswd 인증 추가
현재 설정에 전체 IP 대역이 열려 있어서 추가적인 인증이 필요하다. 그래서 htpasswd로 인증 기능을 추가했다.
RPM 설치 설명할 때 설치한 htpasswd 명령으로 비밀번호 파일을 생성하자.
1 | > htpasswd -bc /etc/squid/passwords user password |
그리고 설정파일에 아래 코드를 추가하자.
/etc/squid/squid.conf
1 | htpasswd 인증 설정 추가 |
포워딩 도메인 제한
마지막으로 아웃바운딩 도메인을 제한해서 보안 이슈 발생을 한번더 차단하자.
/etc/squid/squid.conf
1 | 허용 도메인 추가. |
Caching 기능 끄기
Squid 강력한 기능이라고 하는 Caching 기능이 우리에겐 독이다. 크롤링 시 캐싱된 오래된 페이지를 가져올 경우 문제가 될 수 있기에 끄자. 아래 페이지 링크를 참조하자.
1 | cache deny all |
이제 다 완료됐다. 데몬을 재시작하자.
Python 클라이언트 구현
SOCKS 미지원
솔직히 SOCKS에 대해서 본인은 잘 모른다. 사용해 본적도 없고 Proxy 서버 구성시 사용한다는 정도이다. 인터넷에 Proxy 사용 코드를 보면 아래와 같은 코드를 자주 보게 될 것이다.
1 | import requests |
현재 구성한 시스템에는 해당 소스가 정상동작하지 않는다. 한참 헤매고 나서 원인을 찾았다. squid는 기본으로 SOCKS 프로토콜을 지원하지 않는다. 공식 문서에서 해당 내용을 찾았다.
https://wiki.squid-cache.org/Features/Socks
Squid handles many HTTP related protocols. But presently is unable to natively accept or send HTTP connections over SOCKS.
The aim of this project will be to make http_port accept SOCKS connections and make outgoing connections to SOCKS cache_peers so that Squid can send requests easily through to SOCKS gateways or act as an HTTP SOCKS gateway itself.
해당 문서에 컴파일 옵션으로 주고 소스코드를 컴파일을하면 단일 SOCKS을 지원하는 데몬을 만들어낼수 있다고 한다.
1 | export CFLAGS=" -Dbind=SOCKSbind " |
본인은 굳이 SOCKS을 원하는 것도 아니고 이점을 잘 모르기에 클라이언트 코드를 수정했다.
1 | import requests |
코드 자체 기본 로직은 간단하다. 기본 다이렉트로 서버에 요청을 보내고 차단 이슈가 발생하면 Proxy로 던지게 하면 된다. AWS lambda이기에 할당되는 IP가 한정할 수 없고 모든 IP가 차단될 일이 없기에 기본적으로는 직접 서버로 요청하고 차단 이슈가 발생할 경우 Proxy로 요청하게 구현하면 된다.
정상적으로 요청이 진행되고 있다면 아래 로그와 같이 로그에서 확인 가능할 것이다.
/var/log/squid/access.log
1 | 1681976515.035 539 13.x.x.x TCP_TUNNEL/200 51022 CONNECT xx.xx.com:443 userid HIER_DIRECT/223.130.200.148 - |
마무리
해당 시스템을 구성 후 며칠 동안 사용해 보았는데 잘 동작한다. 성능도 나쁘지 않고 클라이언트 구현시 별도 설정이나 많은 코드가 추가되지 않아서 기존 시스템에서 마이그레이션 하기도 편하다. 다만 차단될 정도의 트래픽을 유발하는 행위는 애초에 만들지 말자!