질문/조언팁/리소스 공유

https://xetown.com/questions/1172070

이런 문제가 생기지 않도록 하기 위한 모범답안입니다.

 

다른 분들 참고하시라고 좀더 구체적으로 알려드립니다.

https를 사용하는 사이트에서는 보통 nginx 설정을 아래와 같이 한 곳에 다 모아 놓곤 합니다.

 

server {

    listen 80;

    listen 443 ssl http2;

    server_name example.com www.example.com;

    root /home/example/public_html;

    charset utf-8;

    # XE rewrite 설정

    # PHP-FPM 연동 설정

    # SSL 인증서 설정

}

 

이렇게 해놓으면 모든 https 접속이 이곳으로 들어가기 때문에, example.com이 아닌 도메인이나 서브도메인, IP 주소 등으로 접속하더라도 (인증서 오류를 무시하면) XE에 접근할 수 있게 됩니다. 서버 상태에 따라서는 심지어 http 요청도 모두 이곳으로 들어갈 수 있습니다. XE는 어느 도메인으로 접속하든 일단 첫 화면은 띄워주도록 되어 있기 때문에, 엉뚱한 도메인이나 IP로 요청한 시점에 공교롭게도 위젯 캐시가 갱신되면 그 도메인이나 IP가 몇 분간 위젯에 남을 수 있습니다.

 

또한 http://example.com, http://www.example.com, https://example.com, https://www.example.com 이렇게 최소 4군데에 동일한 메인화면이 존재하게 되므로 검색엔진에서 중복 콘텐츠라며 페널티을 받을 수 있습니다.

 

이 문제를 해결하기 위해서는, server 블럭(server { ... } 한 세트를 server 블럭이라고 부릅니다)을 3개로 분리하여 정해진 도메인 외에는 모두 리다이렉트 처리해야 합니다. 아래의 예제는 모든 사용자를 https로 보내고, www는 떼어버리는 예제입니다. www를 붙이고 싶다면 녹색과 주황색 부분을 서로 바꾸시면 됩니다. default 설정의 위치에 유의하세요.

 

server {

    listen 443 ssl http2;

    server_name example.com;

    root /home/example/public_html;

    charset utf-8;

    # XE rewrite 설정

    # PHP-FPM 연동 설정

    # SSL 인증서 설정

}

 

server {

    listen 443 ssl http2 default;

    server_name www.example.com;

    location / {

        return 301 https://example.com$request_uri;
        expires epoch;

    }

    # 이곳에서는 사이트 경로 설정이나 XE 설정, PHP 연동 설정 등을 하지 않음

    # SSL 인증서 설정은 위와 동일하게 해야 함

}

 

server {

    listen 80 default;

    server_name example.com www.example.com;

    location / {

        return 301 https://example.com$request_uri;
        expires epoch;

    }

    # 이곳에서는 사이트 경로 설정이나 XE 설정, PHP 연동 설정 등을 하지 않음

    # 단, Let's Encrypt 인증서 발급을 위해 /.well-known/ 폴더는 특별 처리해도 무방함

}

 

이렇게 하면 등록되지 않은 도메인이나 서브도메인으로 https 요청시 두 번째 server 블럭이 캐치하여 첫 번째로 리다이렉트해 줍니다. http 요청시에는 세 번째 server 블럭이 캐치해 주고요. (http 요청을 캐치하는 default 블럭은 다른 파일에 이미 있을 수도 있으니 주의하세요.) 어떤 경우에도 실제 사이트 설정을 해놓은 server 블럭이 default로 처리되지 않도록 하는 것이 핵심입니다.

 

http로 접속한 사용자를 https로 리다이렉트거나, www를 붙이거나 떼거나, 도메인 변경시에도 모두 위와 같은 문법을 응용해야 합니다. 아파치처럼 rewrite를 남용하지 마세요. if 조건문도 가능하면 사용하지 마세요. nginx에서는 server 블럭과 location 블럭을 최대한 활용하는 것이 정석입니다. (사실 아파치에서도 rewrite에 지나치게 의존하기보다는 <VirtualHost>를 여러 개 만드는 것이 더 깔끔합니다.)

 

return 301 아래에 expires epoch; 을 붙여주는 것은 301 리다이렉트가 캐싱되지 않도록 하기 위해서입니다. 301 리다이렉트는 브라우저에서 영원히 캐싱되므로 설정을 잘못 했을 때 되돌릴 방법이 없습니다. 아무리 전문가라도 시행착오를 완전히 피할 수는 없으므로, 캐싱 방지 헤더를 추가하여 만일의 사태에 대비하는 것입니다. 이렇게 하더라도 검색엔진들은 301 코드를 제대로 인식합니다.

 

참고: 라이믹스는 등록되지 않은 도메인으로 접속하면 등록된 도메인으로 일단 리다이렉트한 후 메인화면을 띄웁니다. 따라서 위젯 캐시가 꼬이는 문제는 생기지 않으나, 도메인 변경시 좀더 주의를 기울여야 합니다.

TAG •

글쓴이 기진곰

profile
GitHub 아이디는 @kijin입니다. 사람을 위한 인터넷 생태계의 발전과 웹 보안에 많은 관심을 가지고 있습니다.
오픈소스 도로명주소 검색서버 및 API Postcodify를 개발, 운영하고 있습니다.
우리가 만들어 가는 XE의 새 이름, 라이믹스(Rhymix) 프로젝트에 참여하고 있습니다.
국내외 서버 및 클라우드서버 세팅, 이전, 튜닝해 드립니다.
  • profile
    아. 저희 www 떼어지게 처리 된건가요 ??? 이전 서버에서 제가 그냥 애드온으로 땜빵했거든요.
  • profile profile
    네, 이제 애드온 필요없습니다.
    애드온이 실행될 때쯤이면 이미 XE에서 세션 처리를 시작했기 때문에 다소 늦은 감이 있어요.
  • profile profile
    애드온 이제 버려도 되는군요. 잊고 있었습니다 ㅋㅋ
  • ?
    홈페이지 주소가 https://www.abc.com 인데 http://abc.com 으로 접속시 http://abc.com ->https://abc.com -> https://www.abc.com 이렇게 다중리다이렉팅이 걸리는 문제가있었는데 올려주신 팁 적용하면 해결될거같군요^^ 감사합니다
  • ?
    감사합니다 ^_^
  • ?
    전 잘 모르지만 기진곰님이 만진 서버니 적용 되어 있으리라 믿어 봅니다.
  • ? profile
    글쎄요 ㅋㅋㅋ 언제 세팅했는지에 따라 다를 수도 있어요. Let's Encrypt 무료인증서가 나오면서 SSL을 사용하는 사이트가 급격히 늘어나서 SSL 관련 세팅 기법을 많이 다듬었습니다.^^
  • profile ?
    ㅋㅋㅋ..일단 쓸게요~
  • ?
    다행이 이런식으로 비슷하게 쓰고있네요

    근데 expire epoch 는 꼭 location 블록안에 넣어야 되나요?

    아님 없어도 상관없거나..? 캐시 무시하려면 꼭필요한건지..ㅎ
  • ? profile
    해당 부분 설명해 놓은 것을 읽어보세요.

서버에 요청 중입니다. 잠시만 기다려 주십시오...