Nginx설치 및 보안설정
0. 설치 순서
- nginx 설치
- nginx 관련 보안 설정 :
headers-more-nginx-module빌드 - systemctl start nginx
- sudo systemctl enable nginx : enable 설정
- /var/log/nginx 의 others의 읽기 권한 추가 : 로그 확인을 위한 설정
1. 설치
- https://nginx.org/en/download.html 에서 1.20 버전을 download *dnf download 를 이용하면 1.14 버전이 받아진다.
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
- ngx_http_headers_more_filter_module.so.zip 다운 후 확장자 .zip제거 (.so 파일)
보안설정(계속)- 모두 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에 접근을 시도한다.
- 추가 요청사항
- error 시 error page 외의 화면으로 하나 넣어달라. –> 완료 https://mceex_t.hmsec.com/v1
- 아래 주소로 web browser 를 이용해서 접속하면 404 not found 가 뜨면 된다.
- 보안설정 추가정보(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>