07_Nginx설치 및 보안설정

Nginx설치 및 보안설정

0. 설치 순서

  1. nginx 설치
  2. nginx 관련 보안 설정 : headers-more-nginx-module 빌드
  3. systemctl start nginx
  4. sudo systemctl enable nginx : enable 설정
  5. /var/log/nginx 의 others의 읽기 권한 추가 : 로그 확인을 위한 설정

1. 설치

rpm -Uvh nginx-1.20.2-1.el8.ngx.x86_64.rpm
  • 설치 후, nginx 계정 생성 및 nginx.service 가 등록된다.

설치 확인

systemctl enable nginx
systemctl status nginx
systemctl start nginx
systemctl stop nginx

2. 보안설정

headers-more-nginx-module 빌드

# .so만들기
docker compose up
docker exec -it <continaer_id> /bin/bash

확인

$ cd /from-host
$ ./cp_ngx_http_headers_more_filter_module.sh

보안설정(계속)- 모두 root 계정으로 진행필요

# nginx:nginx (user:group) 가 존재

cat hosts >> /etc/hosts
cp nginx.conf /etc/nginx/nginx.conf

chown nginx:nginx /etc/nginx/*.conf 
chmod 600 /etc/nginx/*.conf

useradd nginx
usermod -s /sbin/nologin nginx

chown nginx:nginx /usr/share/nginx/html
chmod 750 /usr/share/nginx/html

mv /usr/share/nginx/html/index.html /usr/share/nginx/html/uh_main.html
cp error-page.html /usr/share/nginx/50x.html

chown nginx:nginx /var/log/nginx/
chmod 750 /var/log/nginx/ 
chmod 640 /var/log/nginx/*.log

# header filter module
cp /mceadm/install/ngx_http_headers_more_filter_module.so /etc/nginx/modules/
chmod 644 /etc/nginx/modules/ngx_http_headers_more_filter_module.so

# https 인증서
cp /mceadm/install/hmsec_pem.pem /etc/nginx/
cp /mceadm/install/hmsec_pem.key /etc/nginx/
chmod 644 /etc/nginx/hmsec_pem.pem
chmod 644 /etc/nginx/hmsec_pem.key

systemctl start nginx
systemctl status nginx

# log 의 owner 변경
# nginx 실행 후 log 의 owner 가 root:root 으로 해서 생성된다. 그래서 nginx:nginx 로 변경
# 굳이 필요한지는 불확실. 다만 root 가 아닌 경우에도 log 를 쉽게 볼 수 있도록 하기 위해서이다.
chown nginx:nginx /mceadm/apps/nginx/log/ -R

/etc/nginx/nginx.conf

sudo usermod -aG nginx hmc

mkdir -p /mceadm/apps/nginx/log 
mkdir -p /mceadm/apps/nginx/run
chown mceadm:hmc /mceadm/apps
chown nginx:nginx /mceadm/apps/nginx -R
# /etc/nginx/nginx.conf
user nginx nginx;

worker_processes auto;

error_log /mceadm/apps/nginx/log/error.log notice; 
pid /var/run/nginx.pid;

# ###############
# ngx_http_headers_more_filter_module
# ###############
load_module /etc/nginx/modules/ngx_http_headers_more_filter_module.so;

events { 
  worker_connections 1024; 
}

http{

  include         /etc/nginx/mime.types; 
  default_type application/octet-stream;

  # ###############
  # ngx_http_headers_more_filter_module
  # ###############
  more_set_headers 'Server: Userhabit';
  more_set_headers 'X-Powered-By: Userhabit, Inc.';

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                ' ""$http_user_agent" "$http_x_forwarded_for"';

  access_log /mceadm/apps/nginx/log/access.log main;

  sendfile on; 
  #tcp_nopush on;

  keepalive_timeout 65;

  #gzip on;
  
  client_max_body_size 50m;

  include /etc/nginx/conf.d/*.conf;

  server {
    listen 80;
    return 301 https://mceex.hmsec.com; # 개발서버는 mceext.hmsec.com
  }
  server {
    # ####################
    # 수정필요 : 추후 domain 이 설정되면 변경
    # ####################
    listen 443 ssl;
    server_name mceex.hmsec.com; # 개발서버는 mceext.hmsec.com
    ssl_certificate /etc/nginx/hmsec_pem.pem; 
    ssl_certificate_key /etc/nginx/hmsec_pem.key
    ssl_protocols TLSV1 TLSv1.1 TLSV1.2; 
    ssl_ciphers HIGH:!aNULL:!MD5;

    # listen 80;
    # server_name localtest

    #hmse 
    server_tokens off;
    
    error_page 400 401 403 404 500 502 503 504 /50x.html;
    location / { 
      root /usr/share/nginx/html;  
      index uh_main.html uh_main.htm;

      autoindex off;

      dav_methods PUT DELETE MKCOL COPY MOVE;

    }

    location /v3 {
      proxy_pass http://polaris;
    }
    location /v2 {
     proxy_pass http://polaris;

    }

  } 

  upstream polaris {
    # ####################
    # 수정필요 : 추후 dmz 에서 현대차증권 local gateway 가 열리면 변경
    # ####################
    server uhs1.userhabit.io:8080;
    server uhs2.userhabit.io:8080;
    server uhs3.userhabit.io:8080;
    # server 127.0.0.1:8080;
  }
}

/etc/hosts - 추가

...
10.227.171.96 uhs1.userhabit.io
10.227.171.97 uhs2.userhabit.io
10.227.171.98 uhs3.userhabit.io

4. 테스트

  • local 에서 8080 port server 를 하나 열고, curl 을 날려서 확인. 위의 설정으로는 80 이 열려있고, localhost/v2 는 localhost:8080 으로 가게 된다.
python3 -m http.server 8080
curl localhost
curl localhost/v3
  • https 설정이 되고 나서는 브라우저에서 다음 url 을 visit 해보면 된다.
https://mceex.hmsec.com
https://mceex.hmsec.com/v3
  • nginx.service 확인
$ cat/lib/systemd/system/nginx.service 
[Unit]

Description=nginx - high performance web server Documentation http://nginx.org/en/docs/

After=network-online.target remote-fs.target nss-lookup.target

Wants=network-online.target

[Service]

Type=forking
PIDFile=/var/run/nginx pid

Exec Start=/usr/sbin/nginx-c/etc/nginx/nginx.conf
ExecReload-/bin/sh -c/bin/kill -s HUP $/bin/cat /var/run/nginx.pid)" 
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"

[Install]

WantedBy-multi-user.target

5. 기타

  • 상황
    • 도메인, 방화벽 설정 완료 후 동작 확인
  • 확인사항
    • 아래 주소로 web browser 를 이용해서 접속하면 404 not found 가 뜨면 된다.
      • https://mceex_t.hmsec.com/
      • https://mceex_t.hmsec.com/v3 : 현재 url 에 /v3 가 들어가면 proxy_pass 가 되도록 설정이 되어 있는데 ,이부분도 확인됨. 확인방법은 127.0.0.1:8080 으로 보내고, local 에 간단한 static server 띄워서 확인함. 참고로 error log 를 봐도 proxy_pass 가 적용된 url 을 확인할 수 있다.
    • nginx 동작확인
      • https://mceex_t.hmsec.com/ 으로 접속가능
      • 현재 round robin 으로 https://mceex_t.hmsec.com/v3 에 접근하면, 3개의 WAS 들에 번갈아 가면서 request 를 분배시켜준다.
      • 현재 https://mceex_t.hmsec.com/ 로 접속하면 nginx welcome 이 보인다. 이부분은 수정해야 할 수 있다.
      • 현재, https://mceex_t.hmsec.com/Login 을 호출하면 /usr/share/nginx/html/Login 에 접근을 시도한다.
    • 추가 요청사항
  • 보안설정 추가정보(from 현대차증권)
단순히 헤더에서 nginx 버전정보 표기는 server 안에 server_tokens off 옵션으로 처리가 가능하나
문구를 변경하거나 아예 숨기기 위해선 모듈 적용을 해야한다. 여러가지가 있는데 그중 headers-more-nginx-module를 적용하는 방법으로 진행한다.

적용 할 버전과 같은 버전의 nginx 소스 및 headers-more-nginx-module 을 다운로드 받는다
-> http://nginx.org/download/
-> https://github.com/openresty/headers-more-nginx-module/tags

pcre 다운로드 : pcre2 는 오류남
-> https://sourceforge.net/projects/pcre/files/pcre/8.45/

zlib 다운로드
-> https://zlib.net/zlib-1.2.11.tar.gz

다운로드한 파일들을 머신에 업로드 한다.

압축을 풀고 nginx 소스 디렉토리로 이동

configure

-> ./configure --with-compat --add-dynamic-module=../headers-more-nginx-module-0.33 --with-pcre=../pcre-8.45 --with-zlib=../zlib-1.2.11

make modules

objs 디렉토리 안에 ngx_http_headers_more_filter_module.so 파일 확인

/etc/nginx/modules 로 복사

-> cp ./ngx_http_headers_more_filter_module.so /etc/nginx/modules/

nginx 설정 추가
적용 방법은 다양한 패턴들이 있으며 (참고:https://github.com/openresty/headers-more-nginx-module)
아래는 응답 헤더의 Server 값과 X-Powered-By 값을 변경하는 내용이다.
load_module 은 맨위에 선언 함(너무 아래에 있으면 설정 오류 발생함)

-> vi /etc/nginx/nginx.conf

load_module /etc/nginx/modules/ngx_http_headers_more_filter_module.so;
.
http {
 ...
 more_set_headers 'Server: Saerom eMate Talk Demo';
    more_set_headers 'X-Powered-By: Saerom Information Systems, Inc.';
.
nginx 설정 검증
-> nginx -t

이상 없을시 서비스 재기동
-> systemctl restart nginx
  • error page code
<html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>현대차증권</title>

<style id="" media="all">/* cyrillic-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 200;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvr6Hw0aXpsog.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 200;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvr6Hw9aXpsog.woff2) format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 200;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvr6Hw2aXpsog.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 200;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvr6Hw3aXpsog.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 200;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCvr6Hw5aXo.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw0aXpsog.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw9aXpsog.woff2) format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw2aXpsog.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw3aXpsog.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXo.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM73w0aXpsog.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM73w9aXpsog.woff2) format('woff2');
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM73w2aXpsog.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM73w3aXpsog.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  src: url(/fonts.gstatic.com/s/montserrat/v21/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCuM73w5aXo.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* {
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
}

#notfound {
  position: relative;
  height: 100vh;
}

#notfound .notfound {
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
      -ms-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

.notfound {
  max-width: 1020px;
  width: 100%;
  line-height: 1.4;
  text-align: center;
}

.notfound .notfound-404 {
  position: relative;
  height: 200px;
  margin: 0px auto 20px;
  z-index: -1;
}

.notfound .notfound-404 h1 {
  font-family: 'Montserrat', sans-serif;
  font-size: 96px;
  font-weight: 200;
  margin: 0px;
  color: #211b19;
  text-transform: uppercase;
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
      -ms-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

.notfound .notfound-404 h2 {
  font-family: 'Montserrat', sans-serif;
  font-size: 28px;
  font-weight: 400;
  text-transform: uppercase;
  color: #211b19;
  background: #fff;
  padding: 10px 5px;
  margin: auto;
  display: inline-block;
  position: absolute;
  bottom: 0px;
  left: 0;
  right: 0;
}

.notfound a {
  font-family: 'Montserrat', sans-serif;
  display: inline-block;
  font-weight: 700;
  text-decoration: none;
  color: #fff;
  text-transform: uppercase;
  padding: 13px 23px;
  background: #ff6300;
  font-size: 18px;
  -webkit-transition: 0.2s all;
  transition: 0.2s all;
}

.notfound a:hover {
  color: #ff6300;
  background: #211b19;
}

@media only screen and (max-width: 955px) {
  .notfound .notfound-404 h1 {
    font-size: 40px;
  }
}

@media only screen and (max-width: 480px) {
  .notfound .notfound-404 {
    height: 148px;
    margin: 0px auto 10px;
  }
  .notfound .notfound-404 h1 {
    font-size: 40px;
  }
  .notfound .notfound-404 h2 {
    font-size: 16px;
  }
  .notfound a {
    padding: 7px 15px;
    font-size: 14px;
  }
}

</style>

<meta name="robots" content="noindex, follow">
</head>
<body>
<div id="notfound">
<div class="notfound">
<div class="notfound-404">
<h1>현대차증권</h1>
<h2></h2>
</div>
<a href="https://www.hmsec.com/">Go TO Homepage</a>
</div>
</div>

</body></html>