개인 프로젝트에서 nginx를 웹서버로 사용하고 있다. 그 뒤에는 2대의 WAS를 사용하고 있고, nginx upstream 기능을 사용하여 로드 밸런싱을 했다. 그러다 보니 배포시에 아래 upstream 내 server를 주석처리하고 nginx 를 reload 하고 다 배포하고 또 주석 처리하고 nginx reload하고.... 다 처리하고 다시 reload하고... 휴.... 반복 해야 한다. 


upstream.conf

upstream project_was {
least_conn;
server 127.0.0.1:8081 weight=1;
server 127.0.0.1:8080 weight=1;
}


생각보다 이 작업이 시간도 많이 걸리고 사람이 작업을 하다 보니, 실수가 종종 나오곤 했다. 좋은 방법이 없나 고민을 하기 시작했다!



매일 반복적으로 처리하는 업무의 경우, 최대한 자동화를 진행해야 보다 쾌적한 하루를 보낼 수 있다.


위 글처럼 언제나... 귀찮은 일을 반복하는 걸 싫어하기 때문에 방법 찾아보았다.


1.....?

 - Nginx Plus를 구매!

 - https://www.nginx.com/products/pricing/

 - 비싸다.......


다시!!


1. Nginx Upstream 파일을 만들자!

 - 위 upstream.conf 파일도 어찌 보면 단순 텍스트 파일이다.

 

 1) 배포할 서버를 제외하고 Argument로 활성화 시킬 서버를 넣고 위 파일을 새롭게 생성한다.

  - Argument

USE_HOST_INFO_STR=$1

  - 파일 생성

HOSTS=(${USE_HOST_INFO_STR//,/' '})

SERVER_TEXT_TMPL='server HOST weight=1;'
UPSTM_NM_TEXT_TMPL='upstream UPSTM_NM '

UPSTM_NM="tmp_upstream"
BASIC_NGINX_CONF_PATH="/etc/nginx/"
UPSTREAM_CONF_FILE_NM=$UPSTM_NM".conf"

RTN_CONF_STR="${UPSTM_NM_TEXT_TMPL/UPSTM_NM/$UPSTM_NM} { \n"
RTN_CONF_STR+=" least_conn; \n "
for host in ${HOSTS[@]}
do
RTN_CONF_STR+="${SERVER_TEXT_TMPL/HOST/$host} \n"
done
RTN_CONF_STR+="} \n"

echo -e $RTN_CONF_STR > $BASIC_NGINX_CONF_PATH$UPSTREAM_CONF_FILE_NM


2. nginx -t 명령어로 conf파일 valid 체크를 한다.

if nginx -t ; then
echo "=======OK========"
systemctl reload nginx.service
else
echo "=======ERROR========"
exit -1;
fi


3. 전체파일

#!/bin/sh

USE_HOST_INFO_STR=$1

function create_conf_file
{
HOSTS=(${USE_HOST_INFO_STR//,/' '})

SERVER_TEXT_TMPL='server HOST weight=1;'
UPSTM_NM_TEXT_TMPL='upstream UPSTM_NM '

UPSTM_NM="tmp_upstream"
BASIC_NGINX_CONF_PATH="/etc/nginx/"
UPSTREAM_CONF_FILE_NM=$UPSTM_NM".conf"

RTN_CONF_STR="${UPSTM_NM_TEXT_TMPL/UPSTM_NM/$UPSTM_NM} { \n"
RTN_CONF_STR+=" least_conn; \n "
for host in ${HOSTS[@]}
do
RTN_CONF_STR+="${SERVER_TEXT_TMPL/HOST/$host} \n"
done
RTN_CONF_STR+="} \n"

echo -e $RTN_CONF_STR > $BASIC_NGINX_CONF_PATH$UPSTREAM_CONF_FILE_NM
}

function valid_check
{
if nginx -t ; then
echo "=======OK========"
systemctl reload nginx.service
else
echo "=======ERROR========"
exit -1;
fi
}

create_conf_file
valid_check


위 작업을 하면서 쉘 스크립트 작성은 오래 걸리지 않았다. 그러나 프로젝트를 진행하면서 배포를 자동화 해 놓으니 너무 너무 편했다. 


결론!!!!!!!!!!!


 - 반복적인 작업을 자동화하는 습관이 필요하다.

 - 조금만 머리를 쓰면 몸이 편하다!

 - 한번 배포할 때 30초에서 1분 정도 소비되던 반복 작업을 빼니, 좀 더 프로젝트에 집중 할 수 있었다.




* 참고로 위에 스크립트를 업무에 가져다 쓰실 경우 sleep을 충분히 주시기 바랍니다. ^_^ 


1. 소스코드

server

{

 ....

 

  location / 

  {

    valid_referers none blocked server_names *.example.com;


    if ($invalid_referer) {

            return   403;

    }


    ....

  }


}


* 참고페이지

http://nginx.org/en/docs/http/ngx_http_referer_module.html

1. HSTS란?

 - HTTPS를 강제하는 사이트의 경우 HTTP로 접근할 때, 302 Redirect 하는 경우가 많다. 이렇게 될 경우 취약점이 발생한다. (SSL Strip Attack : 하단참고)

 - 유저(브라우저)에게 HTTPS 요청만 허용함을 알려주는 것을 HSTS라고 함.(응답 Header에 추가함.)

 - HSTS는 서버 응답 Header를 통해 등록이 이루어질수도 있지만, Google, Paypal, Twitter의 경우는 크롬 브라우저에 HSTS가 Preload 되도록 강제화 되어있음.

https://www.chromium.org/hsts


* HTTPS로 강제 Redirect 하는 법(Nginx)

return 301 https://$host$request_uri;


* SSL Strip Attack이란?

 - SSL이 적용되어 있는 페이지에 공격자가 공격 대상의 HTTP Request를 스니핑 하여 SSL을 공격하는 방법

 - [공격대상] <- HTTP -> [공격자] <- HTTPS -> [HTTPS Server]

 - 자세한 내용은 구글 검색 ^_^


2. HSTS 설정방법

 1) HTTP Header

Strict-Transport-Security "max-age=86400; includeSubdomains; preload";

 

 - 옵션 설명

옵션명 

설명 

비고 

max-age

 HSTS가 브라우저에 설정될 시간 값 

초단위로 설정, Ex) 60*60*24 = 86,400 = 1day 

 includeSubdomains

 HSTS가 적용될 도메인의 서브 도메인 적용 여부

해당값을 추가하게되면 example.com-> www.example.com, test.example.com까지 확장되어 적용됩니다. 

 preload

 HSTS가 브라우저 측에서 Preload 적용여부

추가시 브라우저 preload list에 추가됩니다. 


  (1) apache httpd

Header always set Strict-Transport-Security "max-age=86400; includeSubdomains; preload"

  (2) nginx

add_header Strict-Transport-Security "max-age=86400; includeSubdomains; preload";


 2) 설정 확인


 


3. HSTS 해제방법

 - 강제로 HSTS를 삭제하는 방법, 사용자의 브라우저에서 삭제해야함.


 1) 서버에서

  (1) apache httpd

Header always set Strict-Transport-Security "max-age=0;"


  (2) nginx

add_header Strict-Transport-Security "max-age=0";


 2) Chrome

chrome://net-internals/#hsts


 


 - Delete domain security policies 에 삭제할 도메인 입력 후 DELETE 버튼 클릭

 - Query HSTS/PKP domain 에 삭제한 도메인 입력 후 Query 버튼 클릭

 - 결과는 'Not Found'가 나온다.


4. TIP

 - HSTS를 추가하면 max-age 값 동안 적용되므로, 테스트 환경에서 max-age를 짧게 잡고, 충분히 테스트 한 후 max-age를 늘리세요.



* 참고링크

 - https://lesstif.gitbooks.io/web-service-hardening/content/ssl-tls-https.html

 - https://rsec.kr/?p=315

 - https://www.ibm.com/support/knowledgecenter/ko/SSEQTJ_9.0.0/com.ibm.websphere.ihs.doc/ihs/tihs_hsts.html


'프로그래밍 > 일반' 카테고리의 다른 글

좋은 코드 작성하기.  (0) 2018.05.01
HSTS(HTTP Strict Transport Security) 개념과 설정  (0) 2018.03.08

nginx conf 파일 내에 다중 if문 조건을 넣고싶다. 허나 nginx에서는 다중 조건 if문 사용이 안된다.

그래서...


1. 하고싶은 소스

if ($host = 'a.example.com' || $host = 'b.example.com'){

  return 301 https://$host$request_uri;

}


2. 변경된 소스

set $is_redirect_val 0;

if ($host = 'a.example.com') {

  set $is_redirect_val 1;

}


if ($host = 'b.example.com') {

  set $is_redirect_val 1;

}

if ($is_redirect_val = 1) {

  return 301 https://$host$request_uri;

}


잘된다.

1. 환경

 - CF + ELB + EC2(nginx)

 

2. 문제

 - 클라이언트 ip주소에 ELB, CloudFront IP들이 덧씌워진다. (ex : 1.1.1.1, 2.2.2.2, 3.3.3.3)

 - ip deny or was에서 처리할때 문제가 발생한다.

 

3. 해결방법

 1) nginx real ip 기능(참고자료)

real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;

 - 위 방법은 또 다른 문제를 발생 시킬 수 있음.

 - 아래 curl을 날려보자.

curl --header "X-Forwarded-For: 1.2.3.4" "http://example.com/"

  - nginx 로그를 켜서 보게되면 사용자 ip가 1.2.3.4로 나오게 될 겁니다.

 

2) nginx real ip + make-nginx-real-ip-conf(소스링크) 사용

 - make-nginx-real-ip-conf로 만든 conf 파일을 include 시킨다. 끝!

 - 아래는 make-nginx-real-ip-conf 프로그램으로 생성한 파일입니다.

#Make at 20170907162608
#your ELB IP
set_real_ip_from 110.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;

#AWS CloudFront IP/CIDR range
set_real_ip_from 13.113.203.0/24;
set_real_ip_from 13.124.199.0/24;
set_real_ip_from 13.228.69.0/24;
set_real_ip_from 13.32.0.0/15;
set_real_ip_from 13.54.63.128/26;
set_real_ip_from 13.59.250.0/26;
set_real_ip_from 204.246.164.0/22;
set_real_ip_from 204.246.168.0/22;
set_real_ip_from 204.246.174.0/23;
set_real_ip_from 204.246.176.0/20;
set_real_ip_from 205.251.192.0/19;
set_real_ip_from 205.251.249.0/24;
set_real_ip_from 205.251.250.0/23;
set_real_ip_from 205.251.252.0/23;
set_real_ip_from 205.251.254.0/24;
set_real_ip_from 216.137.32.0/19;
set_real_ip_from 34.195.252.0/24;
set_real_ip_from 34.226.14.0/24;
set_real_ip_from 35.158.136.0/24;
set_real_ip_from 35.162.63.192/26;
set_real_ip_from 35.167.191.128/26;
set_real_ip_from 52.15.127.128/26;
set_real_ip_from 52.199.127.192/26;
set_real_ip_from 52.212.248.0/26;
set_real_ip_from 52.220.191.0/26;
set_real_ip_from 52.222.128.0/17;
set_real_ip_from 52.46.0.0/18;
set_real_ip_from 52.52.191.128/26;
set_real_ip_from 52.56.127.0/25;
set_real_ip_from 52.57.254.0/24;
set_real_ip_from 52.66.194.128/26;
set_real_ip_from 52.78.247.128/26;
set_real_ip_from 52.84.0.0/15;
set_real_ip_from 54.182.0.0/16;
set_real_ip_from 54.192.0.0/16;
set_real_ip_from 54.230.0.0/16;
set_real_ip_from 54.233.255.128/26;
set_real_ip_from 54.239.128.0/18;
set_real_ip_from 54.239.192.0/19;
set_real_ip_from 54.240.128.0/18;
set_real_ip_from 2600:9000::/28;

# always put the following 2 lines in the bottom of ip list
real_ip_header X-Forwarded-For;
real_ip_recursive on;


3) make-nginx-real-ip-conf 란??

  - AWS에서는 사용중인 ip를  json으로 공유해줍니다.

  - 그중 CloudFront 대역 Ip v4, Ip v6만 파싱합니다.

  - 내부 아이피 대역을 추가합니다. (지인의 말리퀘로 추가된 부분입니다.)

  - nginx real ip에 필요한 CloudFront, ELB 대역만 정리하여 파일로 생성해주는 프로그램입니다.

  * 참고로 https://ip-ranges.amazonaws.com/ip-ranges.json 가 변경되는 내용을 AWS SNS Topic으로 받을 수 있고, 해당 이벤트로 람다를 실행 시킬 수 있습니다.

 

 

 

* 참고링크

 - http://serverfault.com/questions/331531/nginx-set-real-ip-from-aws-elb-load-balancer-address

+ Recent posts