nginx 웹서버의 SSL 보안설정과 HTTPS 라우팅설정 방법(www 도메인 리다이렉팅)

32

지난 글에서 HTTPS 사용을 위한 인증서를 발급받았다면 nginx(엔진엑스) 설정파일을 수정해줄 차례입니다. 아울러 ssl.conf 파일을 생성해서 SSL 보안설정, TLS 지원버전설정등을 해주겠습니다.

참고로 이번글에서 작성하는 nginx의 SSL 보안설정 내용은 보안등급 테스트에서도 전체 평점 A+ 등급이 나오는 설정입니다.

이 글은 리눅스서버  LEMP 스택에 WordPress 설치 시리즈글 연재작의 일환으로 작성되었지만 워드프레스를 사용하지 않는 경우에도 적용가능합니다. 웹서버로 nginx(엔지엑스)를 사용하는 우분투 리눅스 16.09 LTS 서버를 기준으로 설명됩니다.  

검색으로 들어온분들 중 nginx가 아닌 아파치 웹서버의 리다이렉팅 설정을 보려면 아래 링크글을 참고하시기 바랍니다.

 

이번 글은 아래 4가지로 나누어 그 방법과 부수적인 개념을 설명하려고 합니다. 

nginx의 SSL 보안 설정을 위한 암호화 파일 준비하기

nginx 웹서버의 SSL 보안설정 문들은 본래, nginx 라우팅설정파일에 써넣으면 되지만 저는 ssl.conf이라는 이름의 파일을 생성해서 보안설정 코들를 작성하고 그 파일을 라우팅설정 파일에 include 할 예정인데요. 

이게 꼭 ssl.conf 라는 이름일 필요도 없고 파일을 저처럼 따로 빼지 않아도 상관없습니다. 다만 설정문 내용(제가 작성할 ssl.conf의 내용)이 라우팅 설정파일안에 작성되어야한 다는 것만이 중요합니다. ssl.conf 이라는 이름의 파일을 만들어 거기에 보안설정을 적고 다시 그 파일을 다시 라우팅설정파일에 include 하는 이런건 그냥 방법론일 뿐입니다.

 제가 보안이 전문은 아니라서 잘 알지 못하지만 웹사이트를 만들때 항상 보안적측면을 최우선으로 고려합니다만 이번 설정값은 제가 사용하는게 최선이 아닐 수도 있습니다. 시간이 지나면서 기술발전과 해커들의 해킹기술이 발전함에 따라 수정이 필요할 수도 있겠는데요. 이번 챕터에서는 nginx 웹서버를 사용할경우 보안설정은 어떻게 해야할지 알 수 있습니다.

또한 SSL 보안에도 버전과 등급이 있습니다. 수십년의 역사만큼이나 웹브라우저마다 지원가능한 보안버전도 다르고 제 설정대로라면 오래된 웹브라우저는 지원되진 않을 것입니다.

ssl.conf 에 사용할 dhparam.pem 암호화 파일 생성하기

아래에서 만들 ssl.conf 파일의 내용에 추가할 파일인데 이거 만드는 시간이 꽤 걸릴 수 있기때문에(컴퓨터 성능에 따라 다름) 먼저 만들고 가겠습니다.

 

이 파일이름을 보통 dhparam.pem 으로 짓지만 4096비트임을 표시해주기위해 dhparam-4096bit.pem 식으로 지어도 됩니다. 파일경로 지정만 잘해주면 이름이야 어떤들 상관없으니까요. openssl 프로그램은 서버에 이미 설치되어 있을 겁니다(openssl version). 

openssl dhparam -out /저장할/경로/dhparam파일이름.pem 암호화비트수

/etc/nginx/ 폴더 아래에 만들어야하는데 이 폴더가 root의 권한 아래에 있으므로 sudo 접두사를 붙여서 아래처럼 입력합니다.

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

 

암호화 수준은 2048, 4096 처럼 컴퓨터공학에서 쓰이는 숫자 단위로만 쓸수있고 높을 수록 암호를 풀 수 있는 시간이 오래걸리므로 보안이 강하죠. 그대신 HTTPS 성능도 느려집니다. Let’s Encrypt는 다른 인증서들에 비해 좀 느리다는 평이 있습니다. 느릴게 걱정이라면 비트수를 2048로 낮추시기 바랍니다. (2048로 해도 보안등급은 A+입니다. 2048과 4096 비트의 파일을 둘다 만들어놓고 ssl.conf에서 바꿔써볼 수도 있을 것같네요)

openssl 명령어를 사용해서 4096 비트 암호화 파일 생성시작... 화면에 점점점이 가득차며 진행중임을 알려주고 있다



위 화면처럼 점이 계속 찍히면서 작업이 진행중을 알리다가 작업이 완료될 겁니다. 2048비트는 위 화면이 곧바로 끝날것이지만 4096비트 암호화는 시간이 꽤 오래 걸려요.  3~40분 정도?

이게 진행되는 동안 서버에서 CLI 명령어를 이용한 다른 작업을 하고싶다면 위 화면은 그대로 두고 터미널 창을 추가로 새로 열어서 서버에 또 접속하고 하면 됩니다. (윈도우에서는 명령 프롬프트 사용

참고: 진행 중인 위 작업을 멈추고 싶다면 cntorl+c 키를 누르면 됩니다.

작업이 완전히 완료되면 아래처럼 별다른 메시지 없이 명령어 입력가능상태가 되는데 에러가 나면서 에러메시지에 …permission 같은 글자가 보인다면 위에 말한대로 권한문제입니다. 

dhparam.pem 파일 생성 완료

Nginx SSL 인증서 보안 설정: ssl.conf 파일 생성하기

우선은 ssl.conf 라고하는 보안설정 내용이 들어갈 파일을 만들건데 이 내용은 이후 nginx 라우팅 설정파일에 include 해야합니다.

 

/etc/nginx/snippets/ 폴더 안에 만들 건데요. 이 폴더는 ubuntu에겐 수정 권한이 없을 것이므로 CLI에서 만들어야합니다. 아래처럼 root사용자를 쓰기위해서 sudo를 포함한 touch 리눅스 명령어를 통해서 파일을 만들고, chmod로 권한을 777로 개방해서 SFTP 프로그램을 통해 수정가능하게 하고, ls 명령어로 파일이 잘 만들어졌는지 살펴봅니다. 그럼 총 3개의 명령어죠. (명령어 입력시 참고하면 좋은 리눅스 지식: 명령어 시작줄 표시 $과 # )

$ sudo touch /etc/nginx/snippets/ssl.conf
$ sudo chmod 777 /etc/nginx/snippets/ssl.conf
$ sudo ls -l /etc/nginx/snippets/ssl.conf

sudo 명령어로 ssl.conf 파일을 만들고 권한을 변경했다

FTP프로그램 Transmit 5에서 찾아본 ssl.conf파일

 

위에서 설정한 권한 777 은 리눅스 컴퓨터 사용자 아무나 수정이 가능한 권한입니다. 이렇게 권한을 개방한 이유는 위 명령어에서 touch로 파일을 만들때 root 명령어(sudo)로 만들어서 이 파일의 소유자:사용자그룹root:root 이고, FTP 는 ubuntu로 접속했기때문에 이파일의 소유자도도 사용자그룹도 뭣도 아닌 사용자므로 그 ‘아무나’에 속합니다.

이 글에서는 GUI를 다루는 초보사용자를 위해 FTP를 통한 편집을 안내하기위해서 권한설정을 했습니다.  (이 권한은 나중에 다시 644등으로 돌려주는게 좋습니다.)



 

FTP를 쓰지않고 CLI용 텍스트편집기인 vim 이나 emacs, nano 로 수정할거라면 권한을 변경하는 chmod 명령어는 건너띄고 바로 root권한을 가지고 이 파일을 바로 수정하시면 됩니다.  FTP를 통한 파일수정 방법을 모른다면 아래링크를 참고하세요.

ssl.conf 파일에 nginx 보안설정문 작성과 설명

이제 ssl.conf 파일을 열어 아래 내용으로 작성하고 저장해주세요. 여러분이 보는 화면의 폭에따라 줄바꿈이 아닌 곳에서 줄바꿈으로 보일 수도 있으니 그대로 복사해서 붙여놓고 수정하는걸 추천합니다. 각각의 설정문은 세미콜론;으로 끝나고, 같은 줄에서 #기호 이후는 주석문입니다.

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/nginx/dhparam.pem; ###파일을 생성하려면 CLI에서 명령어를 다음과 같이: sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ##강력한 알고리즘 사용
ssl_ecdh_curve secp384r1;

ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;

resolver 8.8.8.8 8.8.4.4; ## 구글이 제공하는 네임서버로 인증서 발급업체와 통신
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Content-Type-Options nosniff;

############# iframe 사용 옵션. 참고: http://bit.ly/x-frames #############
add_header X-Frame-Options "SAMEORIGIN"; ####같은 도메인에서만 iframe 허용
####add_header X-Frame-Options DENY; ####모든 도메인에서 iframe 허용
####add_header X-Frame-Options "ALLOW-FROM https://example.com"; #####특정 도메인에서만 허용

 

위 보안설정은 저도 다른데서 베껴온거라 다 알진 못하는데요. 저도 여기저기에서 참고했습니다.  아래 설명을 참고하세요.

ssl_protocols(SSL 프로토콜): 말했듯 SSL에도 보안등급과 버전이 있습니다.  현재 최신판은 TLS1.3 이지만 아직 표준으로 지정되지 않은 것같고, TLS1.2 만 지원해도 되겠지만 구형 웹브라우저지원을 위해서 이전버전인 TLS1 과 TLS1.1 도 함께 지원하는걸로 했습니다. SSLv2와 SSLV3 프로토콜은 취약점이 있다고 해서 뺐습니다.

ssl_dhparam: 위에서 준비했던 dhparam.pem 파일의 경로가 어디인지 지정합니다. 위에서 자신이 만든 경로와 이름에 유의해서 작성해주도록 합시다.

add_header X-Frame-Options: 위에서 iframe 사용옵션 이하는 3가지 중에 하나만 선택한건데요. 내 웹페이지의 내용이 HTML의 iframe 태그를 통해서 그대로 다른 웹페이지(또는 다른 웹사이트)에 임베딩 될 수 있는데 그 것을 제한하는 옵션입니다. 주석문 처리된 나머지 두개는 참고용일뿐 하나만 적용해야합니다. 위는 제가 개발했던 웹사이트가 같은 도메인의 iframe을 사용하느라 위처럼 SAMEORIGIN을 열어줬던 설정입니다. 제 사이트에서만 허용하는거죠. 제한을 없애려면 아예 해당 내용을 작성하지 않거나 앞에 #기호를 붙여서 주석문으로 처리해주면 됩니다.

 

그리고 X-Frame-Options 또한 웹브라우저 버전별로 호환이 다르다는걸 염두에 둡시다. 참고링크(영문) . 만일 iframe 보안옵션이 허용하지 않는데 iframe 을통해서 제 페이지를 넣는다면 방문자의 웹브라우저 디버그 모드에서는 아래와 같은 에러메시지가 나타나게됩니다

Refused to display in a frame because it set ‘X-Frame-Options’ to ‘deny’. (index):33

참고자료: nginx 공식문서모질라재단 SSL conf 생성기Strong Ciphers 리스트정광섭님의 블로그

 

위 파일내용을 저장하고 다시 CLI로 돌아와 777 권한을 644로 되돌려 ubuntu 사용자의 수정권한을 막습니다.

sudo chmod 644 /etc/nginx/snippets/ssl.conf

 

 이글에서는 아직 nginx 라우팅 설정파일에 위 파일내용을 껴넣지 않았으니 nginx를 재실행할 필요없이 아래 단계를 진행하겠습니다.

중요: 차후에 위 파일 내용을 수정하게 되면 nginx를 재시작해야 서버에 적용됩니다.

 그럼 다음으로는 nginx 라우팅설정을 바로 알아보겠습니다.

nginx 라우팅 HTTPS 설정과 www 리다이렉팅 설정하기

WWW 서브도메인을 메인도메인으로 리다이렉팅, 혹은 그 반대로 해주는 건 사실 DNS설정에서도 CNAME 설정으로도 할 수 있습니다. 하지만 DNS에서는 상세한 콘트롤이 안되고, HTTPS 리다이렉팅은 불가능하며 그때 그때 바로 바꿀 수 없다는 점(TTL시간소요)에서 웹서버 설정에서 해주는게 좋습니다. 제 글에서는 HTTP와 HTTPS를 나누는 라우팅설정을 하는 김에 리다이렉팅도 함께 설정해주겠습니다. 

리다이렉팅 개요: 스위프트의 계획

HTTPS를 지원하게된 이제, 메인도메인이 starry.info라고 한다면 방문자가 접속할 수 있는 블로그의 도메인이 다음과 같은 변수가 있습니다.

  • http://www.starry.info
  • http://starry.info
  • https://www.starry.info
  • https://starry.info

http로 들어오는 모든 방문자를 https 주소로 리다이렉팅 시켜주고, www. 서브도메인으로 들어올 경우에도 메인도메인으로 안내하려고 합니다. 

여러분 또한 최종 도착 도메인을 www가 없는 메인도메인으로 할건지, www가 붙은 서브도메인으로 몰아줄건지를 결정해야합니다. 리다이렉팅을 저처럼 하든 안하든 그건 여러분의 자유입니다. 

 

그러니까 제가 하려는 건 아래와 같습니다:

  • http://www.starry.info는 https://www.starry.info로,
  • http://starry.info는 https://starry.info 로,
  • https://www.starry.info는 https://starry.info로 돌려줘서 최종 도착지가 모두 https://starry.info 가 됩니다.

위처럼 되면 맨 처음게 이상하죠? 곧바로 최종도메인으로 돌려주질 않네요. 저렇게하면 http://www.starry.info로 접속하는 사람은 http://www. -> https://www -> https:// 처럼 리다이렉팅이 이루어지는건데요. 이경우 중간을 건너띄고 곧바로 리다이렉팅 할 수는 있겠으나 그러면 이경웅엔 HSTS(HTTP Strict Transport Security) 라는 것과 호환이 안된다고 하네요.

일개 블로거로서는 HSTS 안되도 별상관 없고 개발자에게는 상관이 있을 수 있으나 개발자라면 그냥 최종도메인으로 바로 접속하는 API, 통신코드를 작성하시면 되므로 그리 중요한 사항은 아니겠지만, 뭐 그냥 그대로 둡시다. 

nginx 라우팅 설정 파일 수정하기

저를 따라 이번 연재작 시리즈를 쭈욱 진행하셨다면 이전의 nginx 라우팅설정은 http 에대해서만 되어있을 겁니다. 다시한번 /etc/nginx/sites-available/default 파일을 열어서 수정하도록 합니다.

아래 설정코드가 제 설정의 최종 내용인데 더 짧게 쓰는 방법도 있긴하지만 보기 쉽게, 이해하기쉽게 server 블락별로 모두 나눴습니다. 

중요: 아래내용 중 starry.info는 제 도메인이름이므로 여러분은 여러분의 도메인에 맞게 수정해야합니다. 인증서 폴더경로를 포함해서 총 13군데 있습니다.

####################################
#####                HTTP                ##########
####################################

###### HTTP www.
server {
    listen 80;
    listen [::]:80;
    server_name www.starry.info;

    include /etc/nginx/snippets/letsencrypt.conf;  ### .well-know/acme-challenge 폴더위치를 알리는 location 블록

    location / {
        return 301 https://www.starry.info$request_uri; ###### HTTPS www로 리다이렉팅
    }
}

###### HTTP
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    server_name starry.info;

    include /etc/nginx/snippets/letsencrypt.conf;   ### .well-know/acme-challenge 폴더위치를 알리는 location 블록

    location / {
        return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅
    }
}

####################################
#####                    HTTPS          ##########
####################################

###### HTTPS www.
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.starry.info;

    ssl_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/starry.info/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
    include /etc/nginx/snippets/ssl.conf; ### SSL 보안설정 ssl.conf 파일 위치 

    location / {
        return 301 https://starry.info$request_uri; ###### HTTPS로리다이렉팅
    }
}

###### HTTPS 메인도메인(최종목적지)
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server ipv6only=on;
    server_name starry.info;

    ssl_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/starry.info/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
    include /etc/nginx/snippets/ssl.conf; ### SSL 보안설정내용경로

    root /var/www/html;
    index index.php index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
        # 워드프레스 고유주소(permalink)를 기본(plain)에서 글이름(post name)등 다른걸로 바꾸었을 때 기존 글들이 404페이지가 되는 것 우회
       if (!-e $request_filename) { 
         rewrite ^.*$ /index.php last; 
       }
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
       fastcgi_read_timeout 300;
    }

    location ~ /\.ht {
        deny all;
   }
}

 

리다이렉팅 룰을 저와 같이 하려면 복사해서 쓰면되는데요. 여러분의 모니터,스마트폰 화면, 웹브라우저 너비가 좁다면 이 포스트 글을 볼 때 줄바꿈이 아닌곳에서 줄바꿈으로 보일 수는 있습니다. 모든 명령어는 한줄당 {, } 또는 ;으로 끝나게 됩니다. #기호 이후는 모두 아무영향을 주지않는 주석문이므로 참고하시기 바랍니다.



위 코드들에대한 대략적인 개념은 시리즈글 전단계에서 한번 설명했습니다.(아래링크 참고)

위에서 새롭게 추가된건 ssl 명령줄들입니다.  starry.info는 여러분의 폴더이름(도메인이름)으로 사용해야합니다.

ssl_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/starry.info/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/starry.info/fullchain.pem;
include /etc/nginx/snippets/ssl.conf; ### SSL 보안설정내용경로

위 4줄중 마지막 ssl.conf 파일을 include(포함) 하는 문장은 ssl.conf 파일의 내용이 저 위치에 그대로 작성되는 것과 마찬가지이고 우리가 작성했던 ssl.conf는 모든 도메인에대해 공통으로 들어가는 SSL 보안설정들입니다. 간결함과 관리, 수정하기 편하게 파일로 빼둔뒤 include문 한줄을 껴넣는거죠.

반면 위 3줄 ssl_certificatessl_certificate_keyssl_trusted_certificate 에대한 pem파일 위치설정은 도메인별로 인증서 파일위치가 다를 수도 있으므로 일일히 작성해줬습니다.

이게 하나의 서버가 한 도메인만 처리하면 위처럼 복잡하게 생각해줄 필요는 없겠지만, 혹여 서버에 여러 도메인에 따른 여러위치의 여러 인증서파일로 분리되어있다면 저렇게 ssl.conf 만 따로 빼는게 관리측면에서 쉽습니다. 설정파일도 간결해지고요. 물론 세세한 보안설정 값을 또 도메인마다 다르게 가져가려고한다면 그역시도 분리해줘야겠지만요.

우분투 서버 방화벽 확인

마지막으로 서버의 방화벽에서 HTTPS 포트(443번)를 열어줬는지 확인해줍시다.

HTTPS 포트가 막혀있을 경우 웹브라우저에서 아래같은 메시지가 나오게 됩니다.

  • ‘연결 실패’ 또는 ‘사이트에 연결할 수 없음’ 
  • ‘페이지 열기 실패’ 또는 ‘페이지를 열수 없음’
  • ‘ 응답하는 데 시간이 너무 오래 걸립니다.’
  • ERR_CONNECTION_TIMED_OUT

사이트 확인 해보기

위파일을 성공적으로 저장했다면 이제 nginx를 재시작해줘야합니다. 

sudo nginx -t 

위 명령어로 설정파일 문법이 이상없는지 확인해봐서 …syntax is ok…test is successful 메시지가 나오는지 먼저 확인한다음 아래 재시작 명령어를 통해 재시작해주세요.

sudo service nginx restart

nginx 재시작 명령어 입력

이제 브라우저 캐시 삭제, 방문기록을 삭제해가면서 여러분의 도메인을 http://starry.info, http://www.starry.info , https://www.starry.info 와같은 형태 모두다 https://starry.info 으로 리다이렉팅 되는지 확인해보기 바랍니다.

그래도 안전하지않음이 나온다면 아래 링크 글을 참고해 이런 경우는 아닌지 확인합시다.

Let’s Encrypt HTTPS용 SSL인증서 자동갱신 방법

Let’s Encrypt의 SSL 자동갱신 설정하기는 전에 제가 작성했던 HTTPS 인증서 자동갱신하기에서 설명한 기초개념, 방법이 같습니다.

다만 해당글에서는 서버에 설치한게 bitnami WordPress 패키지라서 certbot-auto 파일 경로가 이번에 준비한  LEMP 스택과는 다르고, 이번엔 웹서버로 nginx를 사용하므로 최종적으로 작성할 크론탭 스캐줄은 다음과같이 적어야합니다.

6 5,10 * * * /home/ubuntu/certbot-auto renew --renew-hook "sudo service nginx restart"

위 한 줄을 어디에 어떻게 작성해야할지는 bitnami+아파치 조합에서의 예시인 아래 링크글을 잘 읽어보시면 알게될 겁니다.

HTTPS SSL 인증서 자동갱신 등록방법(Let’s Encrypt)

다음단계

 LEMP스택에 WordPress 설치하기 시리즈 연재작 모두 따라하면서 HTTPS 최종 설정까지 성공하셨나요? 그렇다면 축하합니다. 이렇게 연재작이 끝났네요.

이제 WordPress 사용법도 살펴보고, 글을 쓰기 시작하고, 블로그에 게임을 넣어본다거나, 기타 개발을 해보시면 됩니다.

워드프레스에서 이메일을 보내는 기능이 필요하다면 sendmail 설치하기 글을 참고하시고, 추가로 자신의 사이트 보안등급 테스트도 해보세요.

32 댓글

  1. 안녕하세요.
    LEMP 스택 연재글(6작)부터 워드프레스 연재글(9작)까지 총 15단계에 이르는 라이트세일 대장정(?)을 드디어 성공적으로 완료했습니다.

    정말 아무것도 모르는 초보였지만 각각의 글들을 정독하고, 하나씩 따라하면서 흥미가 생기게 되었고 리눅스가 재미있는 세계라는 것을 알게 되었습니다.

    문제가 발생할 때마다 같이 고민해주시고 정확한 처방을 내려주셔서 무사히 끝낼 수 있었네요.

    앞으로도 좋은 포스트 많이 부탁드립니다.

    진심으로 감사드립니다.

    • 잘 마무리 되어서 저 또한 기쁘네요. 저 역시도 조금씩 더 배워가는 계기가 되었어요. 제가 글 발행을 많이 하진 못하지만 좋은 내용들을 체계적으로 쓸 수 있도록 노력하겠습니다.

      블로그내 알림 서비스를 이용하면 새로운 글 중에 유용할 만한 정보들을 놓치지 않을 겁니다.
      https://swiftcoding.org/get-push-notifications

  2. 일반 블로그 홈피로 사용할려고 하는데 “ssl.conf 에 사용할 dhparam.pem 암호화 파일 생성하기” 을 건너뛰어도 사용하는데는 문제없나요?

        • 저도 안해보진 않았는데 없으면 기본 값으로 설정 될 것같긴하네요. 보안등급이 어떻게 될진 모르겠군요.
          그런데 굳이 안하려는 이유가 무엇일까요?

          • 저번에 bitnami 부분을 따라할때는 이런거 없었는데, 그래서 이부분만 건너뛰어서 따라했습니다. 보안등급은 A 나오는데, 일단은 사용하는데 문제가 안보이는데, 이거 건너뛰었다고 나중에 문제되지않을까 궁금해서요.
            (ubuntu는 설정부분이 많네요. )

          • 그래도 기본 설정이란게 있으니 큰 문제는 되지 않을 것같아요. 당시 저 설정 찾아온것도 보안등급이랑 TLS 버전 설정때문에 가져온 설정이라서요. 권장설정정도로 생각하시면 될 것같네요.

  3. -ssl.conf 에 사용할 dhparam.pem 암호화 파일 생성하기-

    이부분을 그냥 안하고 넘어갔는데, 상관없는지요?

  4. ubuntu에서 wordpress 2개 설치중에 자꾸 이쪽부분에서 오류가 생기는데, 어떻게 바꿔야할지 모르겠어요.

    2번째 wordpress 설정 문제가 있다고 나오는데, 숫자가 겹쳐서 그런가요?ㅠㅠ

    sudo nginx -t 하면

    nginx: [emerg] duplicate listen options for [::]:80 in /etc/nginx/sites-enabled/default:99
    nginx: configuration file /etc/nginx/nginx.conf test failed

    이렇게 나옵니다.
    99행에 두번째 도메인 부분있어요.(listen [::]:80 default_server ipv6only=on;)

    (예전 bitnami 설명대로 해서 wordpress 3개까지 만들어서 사용하고 있는데 우분투는 잘 안되네요)

    참고로
    첫번째 wordpress서버를 주석처리하고 두번째만 wordpress 서버만 돌렸을경우는 잘됩니다.(letsencrpy 인증서는 2개 다 받았고요)

    • 두개 도메인 설정하시려면 server 블락 중에서 default_serverdefault_server ipv6only=on; 은 80, 443 포트별로 각각 한 곳에만 있어야합니다. 아마 그거 때문일 것같네요.
      설정파일의 어느 server name에도 정의 되지 않은 다른 도메인으로 들어왔을 땐 default_server로 정의된 server 블락이 동작하게되어 해당 루트로 들어가게 됩니다.

  5. 정말 감사합니다. 그렇잖아도 용량작은걸 골라서, 다시 지우고 해야하나 고민을 했었는데… 감사합니다

  6. 안녕하세요, 덕분에 위드프레스 블로그 만들 수 있었어요. 정말 감사드립니다.

    그런데, 다름이 아니라 질문이 하나 있습니다.

    워드프레스에서 권장하는 파일 및 폴더 권한 설정 방식이 폴더 755, 파일 644, wp-config.php 600이라고 들었는데요.

    스위프트님께서 써주신 강좌를 다 제대로 따라했는데 보니까 /var/www/html 디렉토리에서 폴더와 파일 모두 755로 설정이 되어있더라구요.

    이 상태로 놔두면 보안에 해가 되거나 그렇지 않는지 궁금합니다, 어떻게 설정하면 될까요?

    그리고 혹시 파일이나 폴더 권한 특히 조심해야할 부분이 있다면 알려주시면 감사하겠습니다 🙂

    정성스런 강좌글들 다시 한 번 정말 감사드립니다.

    • 안녕하세요.
      파일권한에대한 권장하는 설정방식은 여러가지 변수에 따라서 같은 권한번호이더라도 적절할 수도 아닐수도 있습니다.
      리눅스 초보에겐 어려운 권한개념때문에 제 블로그글 설명은 비교적 쉬운 방법으로 www 폴더 하위폴더를 몽땅 같은소유자 같은 그룹번호를 부여한 측면이 있긴합니다. 글도 재검토는 해야하는데 따로 개념글을 작성해야할 필요성을 느끼네요.

      우선은 보안과 파일권한에 대해서 너무 큰 걱정은 안하셔도 된다고 먼저 말씀드리고 싶네요.
      그보다 더 중요한건 ‘믿을수있는’ 플러그인과 테마만 설치하는 겁니다. 플러그인과 테마는 애초에 DB의 모든 내용을 알고 쓸 수 있습니다. 파일권한을 뭘로 하든 상관이 애초에 플러그인에서 돌아가는 코드는 워드프레스(DB)에 기록되는 정보를 조작할 수 있으니까요.

      컴퓨터의 사용자는 많은데 폴더와 파일 권한에대해선 소유자, 그룹사용자, 기타다른사용자 3가지로 나누어집니다.
      그리고 파일 권한은 많이 언급되는 것만 쓰자면
      600 : 파일 소유자만 읽고 쓰기
      644: 파일소유자는 읽기,쓰기, 그룹사용자와 다른기타사용자는 읽기만
      755: 파일소유자는 읽기,쓰기,실행. 그룹사용자와 다른기타사용자는 읽기와 실행
      775: 파일소유자와 그룹은 읽기,쓰기,실행. 다른 기타사용자는 읽기와 실행
      777: 모든 사용자는 읽기,쓰기,실행
      이와 같은 권한이 부여됩니다.

      권한번호에 앞서 고려되어야할 것은 이 파일의 소유자와 그룹이 무엇으로 설정되어있는가죠.
      워드프레스에 관해서는 두 사용자가 핵심인데, (제 글대로 설치한대로라면) 우분투 리눅스 컴퓨터 로그인사용자인 ubuntu와 워드프레스를 실행시키는 웹서버인 www-data 입니다. (비트나미 스택의 경우 bitnami와 daemon)
      워드프레스폴더 하위의 파일들을 웹서버(www-data)가 읽지 못하면 워드프레스는 동작하지 않을 겁니다. 참고로 웹서버는 프로그램이고 여기에서는 nginx이죠.
      워드프레스가 돌아가는 모든 동작들은 이 www-data 사용자 권한으로 작동됩니다.
      관리자화면 같은 웹을 통한 워드프레스 파일을 실행시키고 업데이트하고 플러그인을 설치하는데 있어서 이 웹서버에게 워드프레스 하위 폴더 파일에 대한 쓰기 권한이 있어야합니다.

      www-data 만 생각해 볼 때,
      www-data가 wp-config.php의 내용을 읽어야하겠죠. 600이라면 파일소유자만 읽고 쓸수있으니까 그룹사용자로는 권한이 부족할 것이니 결국 wp-config는 www-data가 소유자일겁니다. 그럼 읽기 뿐만 아니라 쓰기도 가능하죠. 결국 이것은 플러그인뿐만 아니라, 웹서버 해킹을 통한 공격에도 wp-config.php는 내용이 조작될 수 있을 겁니다.
      그런데 www-data는 꼭, wp-config.php를 읽어야만 합니다. 애초에 DB 비밀번호를 작성해둔 wp-config.php을 읽는 것만으로도 DB가 노출되니 쓰기권한이 없어도 보안문제는 매한가지입니다.
      결국 파일 소유자가 www-data 인 한에서는 권한이 600이든 775이든 상관없죠.

      ubuntu 사용자권한을 생각해볼 때,
      ubuntu가 걱정되는 상황은 아마도 CLI 서버접속 비밀번호나 pem파일 유출등의 문제로 타인이 ubuntu 계정으로 SSH 접속하는 상황일 겁니다. 여기까지 오면 사실 root 사용자를 쓸 수 있으니 이미 게임끝이긴 하지만 ubuntu 사용자만 생각해봅시다.
      wp-config.php의 권한이 600인건 유효합니다. ubunutu는 wp-config.php를 읽기조차 할 수 없으므로 DB정보도 모르겠죠.
      그렇다면 워드프레스 다른파일에대해선 어떨까요? ubuntu 사용자가 워드프레스 파일을 읽거나 써야하는 상황은 워드프레스 동작과는 무관합니다. FTP로 접속해서 파일을 읽고, 업로드할 때나 권한이 필요한 거겠죠.
      FTP로 접속해서 뭔가를 할 일이 없다면 애초에 그룹사용자에서도 빼도 됩니다. 그러면 권한이 6xx 라면 ubuntu를 원천봉쇄 할 수 있겠죠.
      문제는 설치과정에서 FTP를 사용한다는 점에 있는데요. 이건 순전히 사용자(독자)의 편의를 위했던 것뿐입니다. FTP 사용할때만 잠시 권한을 주고 끝나면 ubuntu의 권한을 막는게 제일 좋겠는데 차후 FTP 사용을 종종 사용하는 입장에서는 번거롭죠. 결국엔 파일 그룹사용자에 ubuntu를 넣고 7xx 권한을 쓰게 됩니다. 그 중에서도 그룹에 쓰기권한을 부여하는 775, 777이겠죠.
      이 시점에서 ubuntu권한이 탈취되면 7xx는 큰 의미가 없어집니다. 이미 ubuntu로 자유롭게 수정가능하니까요.
      wp-config.php만 600이어서 ubuntu가 못 읽는다고 해도(DB 비밀정보는 보호했다고 해도) 다른 많은 php파일을 수정할 수 있으므로 뭐든지 조작가능합니다. 심지어 DB비밀번호를 몰라도 DB에 정보를 읽고 쓰기가 가능합니다. php파일만 수정해두면 실행은 www-data가 알아서 해줍니다.
      예를들어서, index.php파일에 DB정보를 읽고 쓰는 $wpdb를 이용한 코드를 작성했다고 할때, www-data(웹서버)가 그 index.php를 읽어 실행시키면 $wpdb를 사용하기위해서 www-data가 wp-config.php를 읽고 DB 비밀번호를 통해 DB에 접속하게되죠.
      그리고 DB정보를 이용하지 않고도 테마파일을 수정해서 자바스크립트 코드를 삽입하면 되는 거기도 하죠.

      그러면 마지막으로 걱정해야할 건 결국 기타사용자입니다.
      기타 다른 컴퓨터 사용자의(리눅스에는 용도별로 이미 수많은 사용자가 있습니다) 쓰기권한이 있는 777만 아니라면 큰문제는 없을 겁니다. 그런데 이조차도 기타사용자가 탈취되는 문제가 무엇이 있을진 모르겠네요. 해커가 알겠죠.

      결국 서버관리 측면의 워드프레스 보안에서 가장 중요한건 웹서버(www-data)보안과 서버접속(CLI, SFTP)보안이고, 신뢰할 수 있는 플러그인과 테마인가 입니다(애초에 www-data의 권한으로 실행되므로).

      파일권한과 관련해 정 불안하면 /html/하위의 모든 폴더와 파일의 소유자:그룹을 www-data:www-data로 해두고 600으로 해두면 될텐데 CLI 접속해서 매번 작업전에 권한 바꾸고 작업후에 권한을 되돌려야해서 번거롭긴 하겠습니다.

      • 긴 설명 정말 감사드립니다.

        /var/www/html 디렉토리가 775로 설정된 상태에서도 pem 파일을 유출 당한 게 아니거나 검증된 안전한 플러그인과 테마만 사용한다면 해킹이나 보안에 대해서 걱정할 필요는 없다는 말씀으로 이해했는데 맞을까요?

        저는 775 퍼미션으로 설정되면 혹여나 아무나 제 블로그 PHP를 보고 수정하거나 할 수 있는 건가 싶었거든요. 아마 제가 권한에 대한 개념이 부족해서 그런 것 같습니다. 모든 파일과 디렉토리의 소유자, 그룹이 일괄적일 거라고 생각해서 잘못 안 것 같아요.

        이번에 스위프트님 강좌를 보면서 이런 쪽에 약간 관심이 가는 것 같아요. 워드프레스 서버 운영할 때 알아두면 좋을 기초적인 개념들을 공부해보는 것도 괜찮을 것 같다는 생각이 듭니다 🙂

        • 위에 답변한건 어디까지나 파일 권한에 대한 것뿐이고, 파일권한은 nginx 보안이나 OS 보안이 뚫린 뒤의 이야기입니다. 그리고 워드프레스 관리자 비밀번호도 조심해야겠죠.

          파일권한은 어디까지나 해당 서버컴퓨터 사용자(www-data,ubuntu등)에게 부여되는 권한입니다.
          웹을 통해서 오는 방문자(해커)는 일단은 nginx(웹서버) 보안설정을 뚫어야 www-data 권한을 탈취할 수 있을 겁니다.

          방문자가 보는 웹페이지처럼 HTTP 요청은 모두 웹서버인(www-data) nginx가 동작시키는 것입니다. 방문자가 php파일 내용 그대로 볼 수 있다면 그건 php 파일내용이 잘못되었거나(php 문법이 틀려서 그대로 출력) nginx가 잘못 동작하는 것이죠.

          예를 들어 nginx는 php 해석엔진이라고 할 수 는 CGI의 힘을 빌려서 xx.php파일의 내용을 해석하는데, 설정이 잘못되어 nginx와 CGI의 연결고리가 없다면 nginx는 php파일의 내용을 그냥 txt 파일처럼 보여주게 될겁니다.

          하여간 파일 권한 번호 때문에 정상적으로 동작하는 워드프레스 사이트의 php파일이 아무에게나 유출될 일은 없습니다.

          파일권한에 있어서는 워드프레스 폴더 하위의 모든 파일들을 www-data가 읽기만 할 수 있고 수정하지 못하게 하면 좋을텐데
          (플러그인 업데이트나 설치 작업때만 권한을 변경한다든지, 소유자:그룹을 ubuntu:www-data로 해두고 755로 해두고 업데이트는 FTP로만 한다든지…)
          플러그인중에는 평소에 파일을 만들거나 수정해야하는 플러그인도 있을 거라서 상황이 녹록친 않습니다. 많이 귀찮죠.

          • Salt Shaking이었나 그 플러그인에서 상시 권한을 요구하더라구요. 말씀하신 경우가 아닌가 싶습니다.

            아 그렇군요. 일단 스위프트님 강좌대로 제대로 nginx를 구축했으면 걱정할 필요는 별로 없겠군요. 자세하고 쉬운 설명 정말 감사드립니다.

            이번에 구축해보면서 우분투나 서버 관리의 기초 개념 정도는 배워볼까 하는 흥미가 생겼네요. 덕분에 정말 잘 워드프레스 구축했습니다. 너무너무 감사드립니다 ㅠㅠ 스위프트님 강좌가 아니었다면 못 했을 겁니다. 앞으로도 자주 블로그 올 것 같습니다. 감사드립니다 😀

  7. 정말 감사합니다. ^^ 설명을 하나하나 너무 잘 해주셔서 셋팅을 잘했습니다.

    대부분 잘 작동을 합니다. ^^

    그런데… 안드로이드 기본 브라우져에서 접속이 안됩니다. 동일 기기의 크롬으로 실행하면 잘됩니다. 그런데 기본 브라우져는 연결이 안됩니다. SSL 프로토콜 오류 이렇게 뜹니다.

    아이폰과 PC, 맥 등은 모두 다 잘됩니다.

    안드로이드도 크롬으로는 잘되는데… 기본 브라우져로는 안되네요.

    안드로이드 버전이 4 입니다. 안드로이드 버전이 낮아서 그럴까요??

    ㅜㅜ

    • 감사합니다. ^^ 자체 해결했어요. 올려주신 default 셋팅을 섞어서… 우찌 해결이 된 거 같아요 ^^

      너무 좋은 정보가 많아요. ^^ 최곱니다.

      • 고생하셨네요. SSL 같은경우 웹브라우저 호환성을 고려해야합니다. 무료 오픈 인증서 도입취지에 따라 새롭게 출현한 렛츠인크립트를 모든 브라우저가 쳬택한건 아니거든요
        오래된 웹브라우저까지 지원하려면 유료 인증서를 써야하는건 어쩔수 없어요

  8. 안녕하세요! 하나 하나 따라하며 어떻게 여기까지 오긴 했는데 마지막 인증서 자동 갱신 부분이 해결이 안되네요.
    https://drive.google.com/file/d/10qjc_SHkVljlAW4JpqGSpnV14NXm53gW/view?usp=sharing
    링크 이미지처럼 날짜 부분 오류 뜨며 저장이 안되는데요. 사용자(루트, 우분투) 바꿔가면서도 해보고, 인터넷에 있는 다른 명령어도 다 넣었봤는데 다 저런식으로 날짜 오류 문구 뜨면 저장이 안됩니다.
    조언 좀 부탁드려도 될까요. ㅜㅜ 좋은 정보 항상 감사합니다!

  9. 안녕하세요! 상세한 설명 덕분에 무사히 서버이전 마치고 잘 사용하고 있습니다 정말 감사합니다.

    현재 사용중에 한가지 문제가 발생하여, 아무리 시도해도 해결이 어려워 이렇게 여쭙니다.

    워드프레스 페이지에 네이버페이를 연동하여 사용하고 있는데, 네이버 페이측에서 사용하는 java버젼과 nginx 인증서가 충돌하는 문제가 생겨 네이버페이측에서 저희 사이트로 xml파일을 요구할때 오류가 발생 하고 있습니다.

    그래서 네이버 쇼핑과 네이버 페이를 사용하려면 네이버측에서 요구하는 특정 URL이 https가 아닌 일반 http로 접속이 되어야 한다고 합니다.
    모든 다른 접근은 https로 리다이렉팅 하지만 네이버 페이 결제가 뜨는 상품상세나네이버쇼핑 특정 DB url은 http로 접속 하게 하는 방법이 있을까요?

    도움 부탁 드리겠습니다. 감사합니다

    • 안녕하세요. 네이버때문에 고생이 많으시네요.
      nginx의 location 블락 설정을 달리 하면 될텐데요.이전 글에서 nginx 설정파일에대한 이해에 대해 몇가지 써놓았죠. https://swiftcoding.org/nginx-routing#knowledge

      본문의 location 블락의 구조를 보면

      location / {
      ....
      }
      

      에서 location 다음에 오는 슬래쉬 / 부분이 URI 조건입니다. 이 부분은 정규식(Regex)를 사용해 다양하게 URI(메인도메인뒤에 따라오는 주소들)를 맞출 수 있는데요. 슬래쉬는 웹사이트 루트를 말하고, 이것만으로는 정규식 표현이 없는 상태입니다. 그러므로 메인도메인 + / 로 시작되는 모든 도메인일 경우 해당 location 블락이 동작하는 것이죠.

      만일 location /abcd/ { .... } 처럼한다면 이 로케이션 블록은 도메인/abcd/로 시작하는 모든 요청주소에대한 동작을 정의하게되죠.

      80번 포트(http://) 로 들어오는 부분에보면

      ###### HTTP
      server {
          listen 80;
          listen [::]:80 default_server ipv6only=on;
          server_name starry.info;
      
          include /etc/nginx/snippets/letsencrypt.conf;   ### .well-know/acme-challenge 폴더위치를 알리는 location 블록
      
          location / {
              return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅
          }
      }
      

      처럼 되어있는데

       location / {
              return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅
          }
      

      이부분은 도메인명/ 로 시작되는 모든 주소에대해서 (location /) 블럭안 ({} 사이)의 동작을 수행하게 됩니다.

      그리고 그안에는 모든 요청주소 $request_uri 앞에 httpS://도메인명을 붙여서 301 리다이렉팅을 해주는 거죠. 그러면 그것은 이제 443포트의 server블락에게 넘어갑니다.

      그러므로 이런 location 블락의 URI규칙을 달리하면 되겠죠.

      location 네이버페이주소 {
      ...
      }
      
      location 네이버페이가_아닌_주소 {
      ...
      }
      

      location 뒤에 오는 규칙은 정규식이라는걸 사용해 맞출 수 있습니다. 아니면 일일히 일치하는 주소마다 location을 만들어줘야하니까요.

      또는

      본문의 80번 포트(http://) 로 들어오는 부분에서

      ###### HTTP
      server {
          listen 80;
          listen [::]:80 default_server ipv6only=on;
          server_name starry.info;
      
          include /etc/nginx/snippets/letsencrypt.conf;   ### .well-know/acme-challenge 폴더위치를 알리는 location 블록
      
          location / {
              return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅
          }
      }
      

      location / { .....} 블럭 부분의 코드가 모든 요청 uri ($request_uri)를 https로 리다이렉팅해주는 부분에서 if문으로 분기해주면 될 것같습니다.

      return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅 이부분에 if 조건문을 넣어서, 예를 들어 아래처럼

      if ($request_uri !~ "^/users/\w+$") {
         return 301 https://starry.info$request_uri; ###### HTTPS로 리다이렉팅
      }
      

      해주면 특정 URI 규칙(($request_uri !~ "^/users/\w+$"))에 맞지 않을 때만 return 301 ...이 동작하는 구조입니다.

      if ($request_uri !~ "주소규칙") 같은경우 메인도메인 뒤에 따라오는 주소인 $request_uri 가 큰따옴표안의 "..."특정규칙(정규식.Regex를 사용합니다. )과 맞지 않을 때(!~) 조건이 참이 되는 것이죠.

      이 조건이 거짓일때(네이버페이 주소일때)는 if문안의 301 리다이렉트문을 수행하지 않고 건너띄게 되므로 http로 연결될테고, 그것을 처리하기위해서 location 블락 다음에 URI와 php를 처리해주기위한 것들을 다시 추가해야겠네요.

          location / { 
              try_files $uri $uri/ =404; 
              # 워드프레스 고유주소(permalink)를 기본(plain)에서 글이름(post name)등 다른걸로 바꾸었을 때 기존 글들이 404페이지가 되는 것 우회
             if (!-e $request_filename) { 
               rewrite ^.*$ /index.php last; 
             }
          }
      
          location ~ \.php$ {
              include snippets/fastcgi-php.conf;
              fastcgi_pass unix:/run/php/php7.2-fpm.sock;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              include fastcgi_params; 
              fastcgi_read_timeout 300;
          }
      
          location ~ /\.ht {
              deny all;
         }
      
  10. 안녕하세요! 연재글 정말 감사합니다. 지금까지 연재해주신 대로 도메인만 다르게 진행했는데요.
    이거 이전까지 다 동작이 잘 되다가 여기서 HTTPS 적용하고 나서 502 에러가 납니다 ㅠ_ㅠ
    http://doctorsfab.co.kr
    혹시 원인을 알 수 있을까요?

댓글은 익명이나 SNS, wordpress.com 로그인 지원). 마크다운 문법 사용가능(Shift+~ 키로 특정문구 혹은 위아래 ~~~으로감싸서 여러줄을 코드블락으로 작성)