지금 가장 많이 사용해 웹서버 점유율 상위에 랭크되어 있다는 웹서버 NGINX에 대한 관심이 높아지고 있죠. 이 NGINX를 적용한 사이트에서 이미지 핫링크 방지 방법은 여러가지가 있는데요. 오늘은 NGINX 핫링크 방집 방법 3가지를 살펴 보도록 하겟습니다.
NGINX 뿐만이 아니라 아파치 등에서 사용하는 방법에 대해서는 아래 글을 참조하시기 바랍니다.
들어가기 전, NGINX 웹서버 점유율
예전에서는 웹서버로 아파치를 가장 많이 사용했지면 최근 들어서는 가볍고 효율성이 좋은, 특히 많은 사람이 접속하는 사이트에서 자원을 효율적으로 사용할 수 있다는 점때문에 NGINX는 가장 많이 사용하는 웹서버가 되었습니다.
코로나 팬데믹으로 쇼핑 사이트들이 증가해서인지 모르지만 지난 2020년 8월인가를 기점으로 NGINX가 가장 높은 웹서버 점유율을 가진 웹서버로 등극했더군요. 쇼핑용을 위한 웹서버로 NGINX가 많이 선택된 것 같습니다.
2020년 11월 기준 NGINX 점유율 34%로 27%에 그친 아파치를 여유롭게 리드하고 있습니다.
아무튼 NGINX가 가장 많이 사용되는 웹서버가 되었기 때문에 NGINX 사용자가 많을 것이니 여기에서 이미지 핫링크 방지 방법이 더욱 더 유용할 수 있겠네요.
그러면 여기서부터 웹서버 NGINX에서 이미지 핫링크 방지 방법에 대해서 살펴보도록 하겠습니다.
리퍼러 룰 활용 NGINX 핫링크 방지 방안 – 고전적인 방식
첫번째로 소개할 것은 NGINX location 블럭에서 리퍼러를 활용하는 것인데요. 이 방법은 흔하게 소개되는 방법은 아니지만 검색하다가 How to Block Hotlinking with Nginx에서 발견한 방법입니다.
여기서 소개해는 코드 스니핏(code snippet)은 아파치에서 사용하는 형식과 닮아 있습니다.
- css, gif, ico, jpeg, js, png, woff, woff2, ttf, ttc, otf, eot 형식을 제어
허용된 리퍼러가 아니면 403에러를 내라고 설계 - 첫번째 룰은 블랭크 리퍼러를 허용
일부 사용자는 웹 브라우저가 보내는 페이지 레퍼러 정보를 삭제하는 방화벽 설정 또는 바이러스 백신 프로그램을 사용하기 때문에 이 옵션을 추가할 필요가 있음
이를 허용하지 않으면 해당 사용자에게는 모든 이미지가 보여지지 않게 될 수 있음 - 두번째 룰은 자기 사이트 도메인 하위 부분 허용
세번째 룰은 자기 사이트 도엠인 - 네번째부터는 구글을 비롯한 사이트와 구글봇 등을 지정
- 맨 마지막에는 첫번째 룰부터 마직막 룰까지 적용한다는 것 명시
location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff|woff2|ttf|ttc|otf|eot)$ {
if ($http_referer !~ "^$"){
set $rule_0 1$rule_0;
}
if ($http_referer !~ "^http://mysite.com/.*$"){
set $rule_0 2$rule_0;
}
if ($http_referer !~ "^http://mysite.com$"){
set $rule_0 3$rule_0;
}
if ($http_referer !~* "google."){
set $rule_0 4$rule_0;
}
if ($http_referer !~* "search?q=cache"){
set $rule_0 5$rule_0;
}
if ($http_referer !~* "msn."){
set $rule_0 6$rule_0;
}
if ($http_referer !~* "yahoo."){
set $rule_0 7$rule_0;
}
if ($http_user_agent !~* "googlebot"){
set $rule_0 8$rule_0;
}
if ($http_user_agent !~* "msnbot"){
set $rule_0 9$rule_0;
}
if ($http_user_agent !~* "slurp"){
set $rule_0 10$rule_0;
}
if ($rule_0 = "10987654321"){
return 403;
break;
}
}
Code language: PHP (php)
valid_referers 활용 NGINX 핫링크 방지 방안
허용된 리퍼러만 이미지 등 콘텐츠 링크를 허용하는 방안에 대해서는 거의 표준화된 방법인데요.
인터넷 검색하면 기본적으로 이 방법을 소개하고 있습니다. 그만큼 많이 사용되고 사용에도 편하다는 것이겠죠.
이 방법에 대한 수많은 설명이 많이 있지만 “NGINX 이미지 외부 링크 막기 설정 방법”에서 비교적 자세하게 설명되어 있기 때문에 이 글을 기반으로 (일부 먹히지 않는 부분은) 수정 설명해 봤습니다.
NGINX에서 이미지 핫링크 방지는 server 블럭 안의 위치하는 location에서 확장자를 지정, 해당 확장자 파일들은 valid_referers에서 요청하는 경우에만 제대로 보여주고 그 외 리퍼러 요청은 403에러 처리하는 하도록 합니다.
- ($host)으로 해당 사이트가 반영되도록
~.domain. 형식으로 이미지를 보여줘도 되는 사이트 지정
도메인 지정 와이드카드는 오직 *만 제대로 작동하는 것 같음
도메인 지정은 *.google.com 같은 포맷만 제대로 작동하고, ~.google.과 같은 방식은 작동하지 않음- 이미지 요청이 올 경우 보여줄 이미지를 설정하든지 아니면 403 에러 메세지 보여주기 결정
. rewrite (.*)$ /custom/403_forbidden.png redirect;
. return 403; - 어디에서 핫링크를 요청하는지 로그에서 기록
access_log /var/log/nginx/hotlink-access.log;
<code>location ~* \.(jpeg|jpg|gif|png|bmp|svg|swf|ico|zip|7z|ttf|woff|webp|eot)$ {</code>
<code> valid_referers none blocked</code>
<code> server_names ~($host) ~.google. ~.bing. ~.yahoo.;</code>
<code> if ($invalid_referer) {</code>
<code> # rewrite (.*)$ /custom/403_forbidden.png redirect;</code>
<code> return 403;</code>
<code> access_log /var/log/nginx/hotlink-access.log;</code>
<code> }</code>
<code> }</code>
Code language: PHP (php)
map 활용 NGINX 핫링크 방지 방안
이는 map에서 모든 리퍼러를 bad referer로 지정하고, 여기서 bad referer가 아닌 도메인을 지정해 주어 bad referer에 해당되는 모든 리퍼러는 403 또는 404 에러를 내도록 만드는 방법입니다.
이 방법은 이미지 뿐만이 아니라 모든 콘텐츠가 모두 해당되므로 매우 강력한 핫링크 방지 방법이 될 것 같습니다. 하지만 너무 광범위하게 막아 버리기 때문에 어떤 부작용이 있는지 확인해 보면서 계속 적용 유지할지 살펴 봐야 할 것 같습니다.
대개 map은 http 블럭안에 세팅합니다.
map $http_referer $bad_referer {
default 0;
"~google.com" 1;
"~bing.com" 1;
"~yahoo.com" 1;
}
Code language: PHP (php)
그 다음 server 블럭안에 다음과 같이 bad referer에 해당하면 사정없이 404 에러를 내라고 지정하면 됩니다.
if ($bad_referer) {
return 444;
}
Code language: PHP (php)
기타
이미지 핫링크 방지가 작동하는지 확인 방법
그러면 이렇게 다양한 핫링크 방지 방안을 적용 후 이러한 핫링크 방지가 제대로 작용하지는 확인할 필요가 있습니다.
가장 단순한 방식은 이미지 핫링크되어 있는 리퍼러에서 계속 이미지 핫링크가 이루어지고 있는지 확인하는 방법인데요. 이 방법은 캐시 등이 있기 때문에 단기간에 확인이 안될 수 있고, 잘못 판단할 수 있습니다.
이러한 문제를 풀려면 curl -I –referer 명령을 사용해 점검해 볼 수 있습니다. 이래와 같은 형식인데요.
curl -I --referer [러퍼러 도메인] [해당 사이트의 파일]
Code language: PHP (php)
여기서 [해당 사이트의 파일]이라고 적시해 놓았는데요. 해당 사이트명만으는 제대로 확인할 수 없고요. 해당 사이트의 구체적인 파일 이름을 넣어서 확인하는 것이 제댜로 된 결과를 보여 줍니다.
이 작업을 https://risingsunsun.com/473에서 제 이미지를 무단으로 핫링크 걸어서 사용하기 때문에 이를 막고자 시작했기 때문에 다음과 같은 명령어를 사용했습니다. 한글 이름이 제대로 표현되지 않아 파일명이 지저분하게 보입니다.
curl -I --referer https://risingsunsun.com https://happist.com/wp-content/uploads/2017/08/%EC%9A%A9%EC%9D%B8-%EC%8B%A0%EA%B0%88-%EC%B4%9D%EA%B0%81%EC%B9%BC%EA%B5%AD%EC%88%98-%EC%9E%85%EA%B5%AC-7332.jpg
Code language: PHP (php)
이 결과 아래와 같이 403에러 처리했다는 것을 보여 줍니다.
HTTP/2 403
server: nginx
date: Tue, 22 Dec 2020 05:57:53 GMT
content-type: text/html; charset=utf-8
content-length: 146
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
Code language: PHP (php)
중복 명령이 있는 경우는 합쳐야
저의 경우는 이미 jpg나 png 파일에 대해서는 webp 파일로 대체하하는 location 명령을 적용하고 있었습니다.
그런 상태에서 뒷부분에 아미지 파일에 대해서 location 블럭을 추가하고valid_referers 명령을 사용하지 제대로 작동하지 않았습니다.
그래서 webp를 적용한 jpg나 png 이미지 파일에 대해서는 webp 적용 명령과 valid_referers 적용 명령을 사용하고, 이어 나머지 이미지 파일 및 기타 파일 포맷에 대해서는 별도 location 블럭을 만들고 valid_referers 명령만을 적용했습니다.
아래는 제가 적용한 방법이니 참고하시기 바랍니다.
location ~* ^.+\.(jpg|jpeg|png) {
valid_referers none blocked google.com *.google.com google.co.kr *.google.co.kr google.ch *.google.ch google.uk *.google.uk google.com.hk bing.com *.bing.com yahoo.com *.yahoo.com facebook.com *.facebook.com happist.com *.happist.com slowzin.com *.slowzin.com nextrend.co *.nextrend.co goodtrip.kr *.goodtrip.kr puripia.com *.puripia.com *.blog.naver.com/ihappist naver.com daum.net;
if ($invalid_referer) {
return 403;
access_log /var/log/nginx/happist.com_hotlink-access.log;
}
try_files $uri$webp_suffix $uri =404;
expires max;
log_not_found off;
access_log off;
}
location ~* ^.+\.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|webp|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|woff2|wri|xla|xls|xlsx|xlt|xlw|zip|css|js)$ {
valid_referers none blocked google.com *.google.com google.co.kr *.google.co.kr google.ch *.google.ch google.uk *.google.uk google.com.hk bing.com *.bing.com yahoo.com *.yahoo.com facebook.com *.facebook.com happist.com *.happist.com slowzin.com *.slowzin.com nextrend.co *.nextrend.co goodtrip.kr *.goodtrip.kr puripia.com *.puripia.com *.blog.naver.com/ihappist naver.com daum.net;
if ($invalid_referer) {
return 403;
access_log /var/log/nginx/happist.com_hotlink-access.log;
}
log_not_found off;
access_log off;
expires max;
#try_files $uri =404;
include /etc/nginx/security-headers.conf;
}
Code language: PHP (php)
구글 도메인 화이트 리스트
이미지 핫링크 방지를 위해서 리퍼러 화이트 리스트 세팅 시 고려할 것 중의 하나가 구글인데요. 구글 검색 결과를 중요한 트래픽 원천으로 삼는다면 가능하면 모든 구글 사이트를 화이트리스트에 등록하는 것이 좋습니다.
그런데 구글은 국가별로 아주 다양한 도메인을 운영하고 있습니다. google.com, google.co.kr 등등 최근까지 구글 도메인 리스트를 아래에 공유하니 화이트 리스트 작성 시 참고하시기 바랍니다. 저는 이 리스트 전체를 다 포함해 버렸습니다.
.google.com .google.ad .google.ae .google.com.af .google.com.ag .google.com.ai .google.al .google.am .google.co.ao .google.com.ar .google.as .google.at .google.com.au .google.az .google.ba .google.com.bd .google.be .google.bf .google.bg .google.com.bh .google.bi .google.bj .google.com.bn .google.com.bo .google.com.br .google.bs .google.bt .google.co.bw .google.by .google.com.bz .google.ca .google.cd .google.cf .google.cg .google.ch .google.ci .google.co.ck .google.cl .google.cm .google.cn .google.com.co .google.co.cr .google.com.cu .google.cv .google.com.cy .google.cz .google.de .google.dj .google.dk .google.dm .google.com.do .google.dz .google.com.ec .google.ee .google.com.eg .google.es .google.com.et .google.fi .google.com.fj .google.fm .google.fr .google.ga .google.ge .google.gg .google.com.gh .google.com.gi .google.gl .google.gm .google.gr .google.com.gt .google.gy .google.com.hk .google.hn .google.hr .google.ht .google.hu .google.co.id .google.ie .google.co.il .google.im .google.co.in .google.iq .google.is .google.it .google.je .google.com.jm .google.jo .google.co.jp .google.co.ke .google.com.kh .google.ki .google.kg .google.co.kr .google.com.kw .google.kz .google.la .google.com.lb .google.li .google.lk .google.co.ls .google.lt .google.lu .google.lv .google.com.ly .google.co.ma .google.md .google.me .google.mg .google.mk .google.ml .google.com.mm .google.mn .google.ms .google.com.mt .google.mu .google.mv .google.mw .google.com.mx .google.com.my .google.co.mz .google.com.na .google.com.ng .google.com.ni .google.ne .google.nl .google.no .google.com.np .google.nr .google.nu .google.co.nz .google.com.om .google.com.pa .google.com.pe .google.com.pg .google.com.ph .google.com.pk .google.pl .google.pn .google.com.pr .google.ps .google.pt .google.com.py .google.com.qa .google.ro .google.ru .google.rw .google.com.sa .google.com.sb .google.sc .google.se .google.com.sg .google.sh .google.si .google.sk .google.com.sl .google.sn .google.so .google.sm .google.sr .google.st .google.com.sv .google.td .google.tg .google.co.th .google.com.tj .google.tl .google.tm .google.tn .google.to .google.com.tr .google.tt .google.com.tw .google.co.tz .google.com.ua .google.co.ug .google.co.uk .google.com.uy .google.co.uz .google.com.vc .google.co.ve .google.vg .google.co.vi .google.com.vn .google.vu .google.ws .google.rs .google.co.za .google.co.zm .google.co.zw .google.cat
Code language: PHP (php)
참고
서버에서 PNG 이미지 최적화로 사이트 속도 개선 방법
서버에서 JPEG 이미지 최적화로 사이트 속도 개선 방법