Browsing Tag

nginx

NCP

[NCP] AWS to NCloud Server Migration – #2편

안녕하세요. ManVSCloud 김수현입니다.

오늘 “AWS TO NCLOUD SERVER MIGRATION – #2편”에서는 간단한 Install과 제가 기본적으로 설정하는 설정값들을 보여드리며 정보를 공유하고자 합니다.


Base Install

[root@manvscloud-web-pub-kr1 ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)

“[NCP] AWS TO NCLOUD SERVER MIGRATION – #1편”에서 생성한 서버에 기본 설치와 설정 작업을 진행하기로 했습니다.

? Nginx 설치
vi /etc/yum.repos.d/Nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud-web-pub-kr1 ~]# yum install nginx -y

CentOS 7에서는 위와 같이 repo를 추가 후 설치를 진행하면 설치간에 큰 어려움은 없을 것입니다.

이후 LB를 붙이면 Nginx Access Log에서 LB의 로그로 나오기때문에 Client IP를 보기 위해서는 nginx -V 2>&1 | grep ‘http_realip_module’ 로 확인하여 http_realip_module이 있는지 확인이 되어야합니다.

RPM 설치 시 이 모듈이 들어가있는데 컴파일로 설치를 진행할 경우 이 부분을 잘 체크해주셔야합니다.

[root@manvscloud-web-pub-kr1 ~]# nginx -V 2>&1 | grep 'http_realip_module'
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
? PHP 설치
[root@manvscloud-web-pub-kr1 src]# yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
[root@manvscloud-web-pub-kr1 src]# yum -y install epel-release yum-utils
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --disable remi-php54
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --enable remi-php74
[root@manvscloud-web-pub-kr1 src]# yum install -y php php-json php-cli php-gd php-pear php-common php-mysqlnd php-fpm php-mbstring php-opcache php-process php-xmlrpc php-pdo php-xml php-bcmath php-devel php-zip php-mcrypt
[root@manvscloud-web-pub-kr1 src]# yum groupinstall " Development Tools" -y
[root@manvscloud-web-pub-kr1 src]# yum install ImageMagick ImageMagick-devel -y
[root@manvscloud-web-pub-kr1 src]# pecl install imagick
[root@manvscloud-web-pub-kr1 src]# echo "extension=imagick.so" >> /etc/php.ini
[root@manvscloud-web-pub-kr1 src]# systemctl enable php-fpm
[root@manvscloud-web-pub-kr1 src]# systemctl start php-fpm

PHP는 remi를 이용하여 설치를 진행했습니다.
Migration할 때 주의할 점 중 하나는 PHP의 모듈을 맞춰주는 것입니다.
기존 서버와 이전하는 서버에서 php -m 로 확인해줍시다.

? MariaDB 설치
vi /etc/yum.repos.d/MariaDB.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.5/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
yum install MariaDB-server MariaDB-client -y

MariaDB도 repo만 추가해주면 쉽게 설치할 수 있습니다.
MariaDB의 버전은 baseurl 부분에서 10.5 부분을 원하시는 버전으로 변경하면 원하시는 버전으로 설치가 가능합니다.

? Memcached

Memcached의 경우 개인 사이트 운영에 큰 효과를 가져다주지 못한다는 평이 있었으나 개인 블로그 용도뿐만 아니라 다양한 테스트를 해볼 예정이기에 memcached를 도입하기로 했습니다.

[root@manvscloud-web-pub-kr1 ~]# yum clean all
[root@manvscloud-web-pub-kr1 ~]# yum update -y
[root@manvscloud-web-pub-kr1 ~]# yum install memcached -y
[root@manvscloud-web-pub-kr1 ~]# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

/etc/sysconfig/memcached 값을 아래와 같이 변경해주었습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/sysconfig/memcached /etc/sysconfig/memcached_org
[root@manvscloud-web-pub-kr1 ~]# vi /etc/sysconfig/memcached
PORT="11111"
USER="memcached"
MAXCONN="2048"
CACHESIZE="4096"
OPTIONS=""

[root@manvscloud-web-pub-kr1 ~]# systemctl enable memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl start memcached

php-memcached도 설치해줍시다!

[root@manvscloud-web-pub-kr1 ~]# yum install php-memcached -y

php.ini를 보면 session.save_handler가 files로 되어있습니다.

이를 memcached로 변경해줄 것입니다.
아래처럼 작업을 진행할 수 있습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/php.ini /etc/php.ini_org
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path"
  1214	session.save_handler = files
  1222	;     session.save_path = "N;/path"
  1238	;     session.save_path = "N;MODE;/path"
  1247	;session.save_path = "/tmp"
  1332	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# sed -i '1214s/files/memcached/g' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==1222 and print "session.save_path = \"127.0.0.1:11111\"\n"' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path "
  1214	session.save_handler = memcached
  1222	session.save_path = "127.0.0.1:11111"
  1223	;     session.save_path = "N;/path"
  1239	;     session.save_path = "N;MODE;/path"
  1248	;session.save_path = "/tmp"
  1333	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# systemctl restart memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl restart php-fpm

그냥 블로그만 운영하던 서버다보니 크게 설치할 것들이 별로 없습니다.
이제 기본 세팅만 진행해보도록 합시다.


Default Settings

우선 sshd 설정을 먼저 진행하기로 했습니다.
설정 조건은 아래와 같습니다.

  • SSH 포트를 22에서 15222로 변경할 것
  • manvscloud 사용자 생성 및 sudo로 root권한 사용
  • root로 바로 접속할 수 없도록 설정
  • 접속 시 Password가 아닌 Public Key 파일을 이용하여 로그인
[root@manvscloud-web-pub-kr1 ~]# useradd manvscloud
// 먼저 서버에 key 파일을 업로드 한 뒤 작업을 진행하였습니다.

[root@manvscloud-web-pub-kr1 ~]# chmod 400 manvscloud.pem
[root@manvscloud-web-pub-kr1 ~]# mkdir /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# ssh-keygen -y -f manvscloud.pem > /home/manvscloud/.ssh/authorized_keys
[root@manvscloud-web-pub-kr1 ~]# chown -R manvscloud:manvscloud /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 700 /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 600 /home/manvscloud/.ssh/authorized_keys

[root@manvscloud-web-pub-kr1 ~]# id manvscloud
uid=1001(manvscloud) gid=1001(manvscloud) groups=1001(manvscloud)
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud wheel
Adding user manvscloud to group wheel
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud systemd-journal
Adding user manvscloud to group systemd-journal

[root@manvscloud-web-pub-kr1 ~]# grep -E "wheel|systemd-journal" /etc/group
wheel:x:10:manvscloud
systemd-journal:x:190:manvscloud

[root@manvscloud-web-pub-kr1 ~]# cat << EOF > /etc/sudoers.d/10-manvscloud-users
> # User rules for manvscloud
> manvscloud ALL=(ALL) NOPASSWD:ALL
> EOF
[root@manvscloud-web-pub-kr1 ~]# chmod 440 /etc/sudoers.d/10-manvscloud-users
[root@manvscloud-web-pub-kr1 ~]# passwd -l root
Locking password for user root.
passwd: Success

///etc/ssh/sshd_config 파일 수정

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/ssh/sshd_config  | grep -E "Port|PermitRootLogin|PasswordAuthentication"
    17	#Port 22
    38	PermitRootLogin yes
    63	#PasswordAuthentication yes
    65	PasswordAuthentication yes
    88	# PasswordAuthentication.  Depending on your PAM configuration,
    90	# the setting of "PermitRootLogin without-password".
    92	# PAM authentication, then enable this but set PasswordAuthentication
   100	#GatewayPorts no


[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/ssh/sshd_config /etc/ssh/sshd_config_org
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# sed -i '65s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==17 and print " Port 15222\n"' /etc/ssh/sshd_config

[root@manvscloud-web-pub-kr1 ~]# systemctl restart sshd

다음은 php설정을 해줄 것입니다.

우선 php.ini 파일과 www.conf 파일을 수정할건데 pm 값을 조정하는 최적화 작업은 기본 설정에서 제외하였습니다.

php.ini파일에서는 아래와 같이 값을 변경해주었습니다.

   date.timezone = "Asia/Seoul"
   expose_php = Off
   short_open_tag = On
   allow_url_fopen = Off
   max_execution_time = 60
   memory_limit = 128M

이번 이전에서 포인트로 정한 php-fpm의 파일 소켓 통신을 설정하는 부분입니다.
www.conf에서 기존 listen이 127.0.0.1:9000로 TCP/IP 소켓 통신이 기본값인데 이를 /run/php-fpm/www.sock 으로 변경하여 Unix Socket 통신이 되도록 하였습니다.

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = 127.0.0.1:9000
    64	listen.allowed_clients = 127.0.0.1
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s$127.0.0.1:9000$/run/php-fpm/www.sock$g' /etc/php-fpm.d/www.conf
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = /run/php-fpm/www.sock
    64	listen.allowed_clients = 127.0.0.1

이 Unix Socket 방식은 TCP의 소켓과 동일하게 API로 데이터를 주고받을 수 있는데 이는 로컬 파일 기반 소켓이라서 Nginx와 함께 쓰기 위해 php-fpm를 같은 로컬내에 존재하도록 하였습니다. 이 방식은 localhost 내에 프로세스 간 통신이라 속도도 우월하고 메모리 소모를 줄일 수 있습니다.

? nofile 설정
vi /etc/security/limits.conf
*               soft    nofile          65535
*               hard    nofile          65535

위 설정을 해주지 않으면 파일 열기 최대 개수가 soft/1024, hard/4096이 default인 것으로 기억합니다.

? History
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=0
[root@manvscloud-web-pub-kr1 ~]# sed -i '78s/0/5000/g' /etc/profile
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=5000
[root@manvscloud-web-pub-kr1 ~]# echo export HISTTIMEFORMAT=\"[%F %T] \" > /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# chmod 755 /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# init 6

저는 history를 자주 이용하는 편입니다.
그런데 기본 설정을 하고 다음 날 서버에 접속했는데 history가 하나도 남아있지 않아 확인해보니 HISTFILESIZE가 0으로 되어있어 이를 변경해주기로 하였습니다.

값을 5000으로 변경해주고 HISTTIMEFORMAT을 주어 history에 시간대도 확인할 수 있도록 설정해두었습니다.

Nginx와 MariaDB 설정은 다음 #3편에서 스토리지 추가 및 NAS 연결과 함께 설정을 진행할 것입니다.


Personal Comments

#3편에서는 “ManVSCloud 신규 Architecture” 공개와 함께 스토리지 추가 및 NAS 연결에 대한 포스팅을 진행할 것입니다.

제가 이번에 진행하는 AWS to NCloud 이전 작업에서 설정되는 부분이나 이렇게 이전이 될 수도 있구나하는 걸 재밌게 봐주셨으면 합니다.

긴 글 읽어주셔서 감사합니다.


IT/Linux/Kubernetes

CentOS7, Rocky 8에서 HTTP/2(h2) 사용하기

안녕하세요. ManVSCloud 김수현입니다.

오늘은 CentOS 7 버전과 Rocky Linux 8.4 버전에서 HTTP/2를 적용해보려 합니다.
이전 포스팅 중에 CentOS 6에서 적용 후 CentOS 7를 포스팅하려고 했는데 Rocky Linux 8버전의 경우 버전 자체가 높아서 한 번에 포스팅하기로 했습니다.

먼저 HTTP/2(H2)에 대해 궁금하신 분들은 아래 먼저 포스팅된 링크를 참고하시기 바랍니다.


Using HTTP/2 on CentOS 7

먼저 CentOS 7 버전에서는 CentOS 6과 같이 버전이 안맞는 것들이 있습니다.
CentOS 6 포스팅에서 업로드 됐던 이미지를 참고해서 한 번 알아보도록 합시다.

CentOS 7 설치 후 Apache를 yum으로 설치해보면 2.4.6 버전이 설치가 됩니다.
Nginx는 따로 repo를 추가해줘야하고 php도 5.4 버전, curl도 7.29 버전이 설치되어있죠.
물론 openssl은 1.0.2g 이상 버전인 1.0.2k 버전이 설치되어있습니다.

오늘은 크게 CentOS 7에서 nginx yum 설치 방법, PHP remi repo로 yum 설치를 작성해보겠습니다.
(PHP 컴파일은 아래 링크를 참고해주세요. 물론 8버전이라 참고용입니다.
특정 버전 컴파일이 어려우실 경우 댓글 남겨주시면 따로 특정 버전 컴파일 방법에 대해 포스팅 해드리겠습니다.)


? Nginx 설치용 repo

CentOS 7에서 nginx를 yum으로 설치하려면 아래와 같이 repo 파일을 생성해야 yum으로 설치할 수 있습니다.

vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud ~]# yum list | grep nginx
nginx.x86_64                                1:1.20.1-1.el7.ngx         nginx   

? PHP remi repo를 이용하여 설치 방법

PHP를 remi repo로 설치하는 방법은 매우 간단합니다.
아래와 같이 두 줄만 입력한다면?!

[root@manvscloud ~]# yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm 
[root@manvscloud ~]# yum -y install epel-release yum-utils

끝입니다. 이미 준비가 완료됐습니다.

yum install php 를 하면 아직 php5.4 버전으로 설치가 되려고할텐데 yum-config-manager 명령어를 이용해서 버전을 변경해줄 것입니다!

어떤 버전이 있나 한 번 봅시다.

[root@manvscloud ~]# yum list | grep -E 'php[50-90]' | grep -v 'x86_64' | awk -F- '{print $1}' | sort | uniq
php54
php55
php56
php70
php71
php72
php73
php74
php80
php81

php5.6 으로 설치를 한다고 예를 들었을 때 아래와 같이 사용할 수 있습니다.

[root@manvscloud ~]# yum-config-manager --enable remi-php56

이후 yum install php를 하면 php 5.6이 설치가 될 것입니다.
이후 php를 7.4버전으로 재설치를 해야할 경우 yum remove php로 5.6버전 제거하고 아래와 같이 7.4 버전을 설치할 수 있습니다.

[root@manvscloud ~]# yum-config-manager --disable remi-php56
[root@manvscloud ~]# yum-config-manager --enable remi-php74
[root@manvscloud ~]# yum -y install php

Using HTTP/2 on Rocky Linux 8

우선 8버전대부터는 HTTP/2 설정을 위해 버전에 대한 걱정이 필요가 없습니다.
아래는 Rocky Linux 8.4버전에서 dnf 설치 시 또는 이미 설치되어있던 버전들입니다.

apache : 2.4.37
nginx : 1.14.1
php : 7.2.24
openssl : 1.1.1g
curl : 7.61.1

버전에 대한 필요 조건이 이미 완성되어있는 상태입니다…
그냥 편하게 설치해서 쓰면 됩니다.?


Personal Comments

CentOS 6 에서 HTTP/2 사용하기 포스팅과 이번 CentOS 7, Rocky Linux 8에서 HTTP/2 사용하기를 보면 HTTP/2를 적용하는데에 큰 어려움이 없을 거라 생각됩니다.

만약 포스팅을 읽어보시고 특정 버전에서 설정하기가 어렵거나 잘 설정이 되지않을 경우 댓글 남겨주시면 답변드리도록 하겠습니다.
다들 코로나 조심하시고 다음 포스팅으로 찾아뵙겠습니다.

긴 글 읽어주셔서 감사합니다.

IT/Linux/Kubernetes

What is HTTP/2(h2)? & CentOS6 HTTP/2

안녕하세요. ManVSCloud 김수현입니다.

오늘은 CentOS 6에서 HTTP/2를 적용해보려 합니다.
CentOS 6은 2020년 11월 30일 이미 지원이 중단된 OS지만 아직 쓰고 계시는 사용자들이 많아 CentOS 6부터 적용 방법을 작성하기로 했습니다.


WHAT IS HTTP/2(H2)?

현재 HTTP/3 까지 출시되었으나 아직까지 많은 유저들은 1999년에 출시된 HTTP1.1을 가장 많이 사용하고 있습니다.
최근들어 HTTP/2를 적용하는 분들이 늘어나고 있어 HTTP/2에 대해 소개를 해드리고자 합니다.

우선 HTTP/2는 HTTP/1.1을 대체하는 것이 아닌 확장한 것인데 HTTP 메소드, 상태 코드, URI, 헤더 필드를 사용하여 동일하게 유지되고 있습니다.

HTTP/1.1로 시작하여 클라이언트가 HTTP/2를 지원하면 연결이 업그레이드 되는 방식입니다.

https://blog.knoldus.com/still-not-switch-to-http-2/

HTTP1.1은 연결 시 하나의 요청과 응답만 처리하기에 동시 데이터 전송이나 여러개의 리소스를 처리하는데에 속도와 성능이 떨어집니다.(전체 용량에 도달하기 전 여러 번의 소규모 전송으로 인한 지연 발생) 또한 서버와 클라이언트 간에 추가 요청이나 메타데이터 교환으로 반복적인 헤더와 쿠키 전송으로 응답 속도가 느려지는 현상이 나타납니다.

HTTP/2를 사용하게되면 이러한 문제를 해결할 수 있습니다. 클라이언트가 단일 TCP 연결을 통해 다수의 모든 요청을 동시에 보낼 수 있게 됩니다.
다만 무조건적으로 HTTP/2가 좋은 것만은 아니기에 내가 운영하는 서비스가 HTTP/2를 사용하기에 적합한지 판단이 필요합니다.

HTTP/2를 사용하게될 경우 단일 연결을 사용하여 동시 요청을 보내게 됩니다. 이는 예측할 수 없는 스파이크가 발생할 수 있는 원인이 될 수 있습니다. 게다가 HTTP/2 Server Push 기법을 이용하여 클라이언트가 요청하기 전에 서버가 클라이언트로 리소스를 보낼 수 있습니다. 이는 리소스를 선점적으로 로드하는데 도움이 되지만 이 또한 재방문자가 캐시된 파일 복사본이 있을 수 있으며 이 경우 서버에서 리소스를 푸시하지 않도록 Push Cache를 인식하도록 해주어야 합니다.(Cache-Control max-age 등 헤더 적용)

HTTP/2 사용은 응답 시간이 중요하지 않은 애플리케이션, 제한된 IoT 장치나 안정적인 연결이 필요한 곳 그리고 WebSockets, Server-Sent Events (SSE), Pub/Sub 메시징과 같이 적절한 기술이 사용되는 경우 등이 적합하다고 볼 수 있겠습니다.

HTTP/2를 적용하기 위해서는 조건이 있습니다.
만약 Apache를 사용할 것이라면 Apache 2.4.17버전 이상이 이어야하며 openssl 버전도 1.0.2 이상이 되어야합니다. PHP의 경우 libcurl 사용 즉, cURL을 이용하여 HTTP/2 POST를 요청하기 위해서는cURL 7.43 이상, PHP 버전도 5.5.24 이상의 환경이 필요합니다.

오늘은 간단하게 CentOS6에서 Apache로 http2 사용하기를 준비했습니다.


Using HTTP/2 on CentOS 6

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_org
vi /etc/yum.repos.d/CentOS-Base.repo

우선 CentOS6은 지원 중단으로 Base repo를 아래와 같이 변경해주었습니다.

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
release=$releasever&arch=$basearch&repo=os&infra=$infra
baseurl=https://vault.centos.org/6.10/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#released updates 
[updates]
name=CentOS-$releasever - Updates
release=$releasever&arch=$basearch&repo=updates&infra=$infra
baseurl=https://vault.centos.org/6.10/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
release=$releasever&arch=$basearch&repo=extras&infra=$infra
baseurl=https://vault.centos.org/6.10/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
baseurl=https://vault.centos.org/6.10/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
release=$releasever&arch=$basearch&repo=contrib&infra=$infra
baseurl=https://vault.centos.org/6.10/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

만약 위와 같이 Base repo를 변경했는데도 정상적으로 yum 설치가 되지 않는다면
지원이 중단된 다른 repo가 있는지 확인해보신 후 중단된 repo를 제거 및 yum clean all 후 재진행 해보시기 바라며 그 후에도 되지않는다면 /etc/resolv.conf 에 nameserver가 정상적으로 등록되어 있는지 확인해보시기 바랍니다.

[root@manvscloud ~]# yum update -y
[root@manvscloud ~]# yum install wget perl gcc zlib-devel epel-release -y

위는 필수 설치 패키지 입니다.

기존에 운영하고 계시던 서비스가 존재한다면 yum update 전에 update 시 예외처리가 필요한 패키지들을 반드시 exclude해주시기 바랍니다.

yum update –exclude= 방식으로 exclude할 수 있으며 /etc/yum.conf에 exclude 설정을 해줄 수도 있습니다.


Install openssl and upgrade version

<OpenSSL Site>

openssl부터 설치해보도록 합시다.
CentOS 6은 기본적으로 1.0.1버전의 openssl이 설치되는데 1.0.2를 설치해주기 위해 컴파일 작업을 진행할 것입니다.

// 컴파일 설치 진행
[root@manvscloud ~]# cd /usr/local/src
[root@manvscloud src]# wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz
[root@manvscloud src]# tar zxvf openssl-1.0.2u.tar.gz
[root@manvscloud src]# cd openssl-1.0.2u
[root@manvscloud openssl-1.0.2u]# ./config --prefix=/usr/local/openssl shared zlib
[root@manvscloud openssl-1.0.2u]# make
[root@manvscloud openssl-1.0.2u]# make install

// ldconfig 및 버전 확인
[root@manvscloud openssl-1.0.2u]# echo "/usr/local/openssl/lib" >  /etc/ld.so.conf.d/openssl.conf
[root@manvscloud openssl-1.0.2u]# cat /etc/ld.so.conf.d/openssl.conf 
/usr/local/openssl/lib
[root@manvscloud openssl-1.0.2u]# ldconfig
[root@manvscloud openssl-1.0.2u]# mv /usr/bin/openssl /usr/bin/openssl-1.0.1
[root@manvscloud openssl-1.0.2u]# ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl
[root@manvscloud openssl-1.0.2u]# openssl version
OpenSSL 1.0.2u  20 Dec 2019

// 기존 certs 복사 
[root@manvscloud certs]# cp -avp /etc/pki/tls/certs /usr/local/openssl/ssl/
`/etc/pki/tls/certs/ca-bundle.crt' -> `/usr/local/openssl/ssl/certs/ca-bundle.crt'
`/etc/pki/tls/certs/Makefile' -> `/usr/local/openssl/ssl/certs/Makefile'
`/etc/pki/tls/certs/renew-dummy-cert' -> `/usr/local/openssl/ssl/certs/renew-dummy-cert'
`/etc/pki/tls/certs/ca-bundle.trust.crt' -> `/usr/local/openssl/ssl/certs/ca-bundle.trust.crt'
`/etc/pki/tls/certs/make-dummy-cert' -> `/usr/local/openssl/ssl/certs/make-dummy-cert'

위와 같이 진행해준다면 openssl 버전이 1.0.2로 설치가 된 것입니다!


Apache + apr, apr-util, pcre

yum install -y nghttp2 libnghttp2 libnghttp2-devel gcc-c++ libstdc++-devel expat-devel pcre-devel

이제 HTTP/2 적용을 위한 Apache를 설치해봅시다.

apache 2.4 버전부터는 apr과 apr-util도 설치해주어야하는데 우선 apr 설치 과정입니다.

[root@manvscloud ~]# cd /usr/local/src
[root@manvscloud src]# wget http://mirror.apache-kr.org/apache/apr/apr-1.6.5.tar.gz
[root@manvscloud src]# tar zxvf apr-1.6.5.tar.gz 
[root@manvscloud src]# cd apr-1.6.5
[root@manvscloud apr-1.6.5]# ./configure --prefix=/usr/local/apr
[root@manvscloud apr-1.6.5]# cp -arp libtool libtoolT
[root@manvscloud apr-1.6.5]# make
[root@manvscloud apr-1.6.5]# make install

아래는 apr-util 과정입니다.

[root@manvscloud ~]# cd /usr/local/src
[root@manvscloud src]# wget http://mirror.apache-kr.org/apache/apr/apr-util-1.6.1.tar.gz
[root@manvscloud src]# tar zxvf apr-util-1.6.1.tar.gz 
[root@manvscloud src]# cd apr-util-1.6.1
[root@manvscloud apr-util-1.6.1]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
[root@manvscloud apr-util-1.6.1]# make
[root@manvscloud apr-util-1.6.1]# make install

pcre도 설치해줄 건데 이후 modsecurity를 사용하기 위해서도 pcre가 필요합니다.

[root@manvscloud ~]# cd /usr/local/src
[root@manvscloud src]# wget https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz
[root@manvscloud src]# tar zxvf pcre-8.43.tar.gz 
[root@manvscloud src]# cd pcre-8.43
[root@manvscloud pcre-8.43]# ./configure --prefix=/usr/local/pcre
[root@manvscloud pcre-8.43]# make
[root@manvscloud pcre-8.43]# make install

Apache 2.4버전을 컴파일할 모든 준비가 되었습니다.
우선 아래 옵션을 보시면 event방식으로 설치했습니다.

[root@manvscloud ~]# cd /usr/local/src
[root@manvscloud src]# wget http://archive.apache.org/dist/httpd/httpd-2.4.48.tar.gz
[root@manvscloud src]# tar zxvf httpd-2.4.48.tar.gz 
[root@manvscloud src]# cd httpd-2.4.48
[root@manvscloud httpd-2.4.48]# ./configure --prefix=/usr/local/apache \
--enable-mods-shared=all --enable-http2 \
--enable-ext-filter --enable-ssl --with-ssl=/usr/local/openssl \
--enable-so --enable-cache --enable-proxy \
--enable-deflate --enable-suexec --enable-file-cache \
--with-mpm=event --with-apr=/usr/local/apr \
--with-apr-util=/usr/local/apr-util \
--with-pcre=/usr/local/pcre/bin/pcre-config \
--enable-modules=all --enable-module=shared
[root@manvscloud httpd-2.4.48]# make
[root@manvscloud httpd-2.4.48]# make install

(event 방식으로 설치 시 event + fcgi proxy + php-fpm 구조가 일반적입니다.)
왜 event 방식으로 설치했느냐?

prefork 방식은 http/2를 지원하지 않습니다.
prefork 방식이 지원되지 않는 이유는 무엇인가?에대한 질문에 대답은 간단합니다.
HTTP/2는 클라이언트가 단일 TCP 연결을 통해 서버에서는 다수의 모든 요청 즉, 동시 요청을 보내야합니다.

prefork의 단일 스레드 요구 사항을 HTTP/2에 매핑하는 것이 불가능한 것입니다.
처리 모델의 충돌이라고 볼 수있죠. (worker와 event는 다중 스레드 지원)

[root@manvscloud ~]# echo "PATH=$PATH:$HOME/bin:/usr/local/apache/bin" >> /etc/profile
[root@manvscloud ~]# echo "export PATH"  >> /etc/profile
[root@manvscloud ~]# tail -n 2 /etc/profile
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/apache/bin
export PATH
[root@manvscloud ~]# source /etc/profile

/usr/local/apache/bin 아래 명령어들을 편하게 사용할 수 있게 위와 같이 등록해주었습니다.
이제 apache에서 모듈을 추가해줍시다.

// 모듈 확인
[root@manvscloud ~]# apachectl -M | grep http2

//http2 모듈 확인
[root@manvscloud ~]# cat -n /usr/local/apache/conf/httpd.conf | grep http2
   144	#LoadModule http2_module modules/mod_http2.so

//주석 제거
[root@manvscloud ~]# sed -i '144s/#LoadModule/LoadModule/g' /usr/local/apache/conf/httpd.conf

//모듈 적용 확인
[root@manvscloud ~]# apachectl -M | grep http2
 http2_module (shared)

// Protocols 추가
[root@manvscloud ~]# cat << EOF >> /usr/local/apache/conf/httpd.conf 
> <IfModule http2_module>
>         ProtocolsHonorOrder On
>         Protocols h2 h2c http/1.1
> </IfModule>
> EOF

위 작업 후 apachectl start를 하여 apache를 실행해주고 웹사이트가 정상적으로 잘 출력되는지 확인해보시기 바랍니다. Apache가 정상적으로 실행됐는데 페이지 출력이 안되면 iptables가 실행되어있지 않은지? 상단 방화벽 등 어딘가에 막히는 것이 없는지 확인해보시고 그래도 출력이 안되신다면 /usr/local/apache/logs 아래 생성된 로그를 참고하여 해결이 필요합니다.

HTTP2.Pro에서 HTTP/2가 잘 적용되었는지 확인해보니 잘 적용되었다고 나오는군요.
해당 사이트는 아래 링크를 통해 바로 접속이 가능합니다.


Nginx

[root@manvscloud ~]# yum list nginx
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * epel: d2lzkl7pfhq30w.cloudfront.net
Available Packages
nginx.x86_64                                                                                                                         1.10.3-1.el6                                                                                                                         epel

[root@manvscloud ~]# nginx -V
nginx version: nginx/1.10.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' --with-ld-opt=' -Wl,-E'

CentOS 6에서 Nginx는 epel에서 1.10.3으로 주네요.
openssl 버전만 맞춰준 뒤에 yum 설치만 해도 됩니다. nginx -V 옵션으로 보면 –with-http_v2_module 옵션이 보이시나요?

단 Nginx에서 http2 적용 테스트 시 주의할 점이 있다면 아래와 같이 HTTPS(443) SSL 설정을 해줍시다.
listen 80 http2 default_server; 으로 설정할 경우 사이트 접속이 안되고 다운로드가 됩니다.?

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
.
. 생략
.
}

CentOS 6에서 Nginx는 크게 어려움이 없을 것으로 보입니다.


Et cetera

나머지는 도움될만한 내용만한 자료만 첨부해두도록 하겠습니다.

cURL은 위 링크를 참고하면 HTTP/2 적용을 위해 cURL을 설치하는 과정이 나와있습니다.
물론 무작정 영상 그대로 따라하기보다 영상에서 주는 옵션을 보며 해당 옵션과 경로가 나의 환경에 맞는지 검토하는 것은 필수입니다.

마지막으로 Tomcat은 className을 org.apache.coyote.http2.Http2Protocol로 설정해주어야합니다.

<Connector port="8080" protocol="HTTP/1.1">
.
. //생략
.
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
.
. //생략
.
</Connector>

Tomcat 역시 버전만 맞춰주면 크게 어려울 것 없어보입니다. ?


Personal Comments

지금까지 CentOS 6에 HTTP/2를 적용에 대해 알아보았습니다.
앞으로 CentOS 7, Rocky 8, Naver Cloud Platform Load Balancer, AWS ELB 등에서 HTTP/2를 적용하는 방법에 대해서도 추가적으로 포스팅 될 예정입니다.

긴 글 읽어주셔서 감사합니다.

NCP

[NCP] Load Balancer 사용 시 웹서버 로그에서 Client IP를 볼 수 있을까?

안녕하세요. ManVSCloud 김수현입니다.

오늘은 Naver Cloud Platform에서 LOAD BALANCER 사용 시에 웹서버 내 로그에 찍히는 IP가 Client IP가 찍히도록 설정하는 방법에 대해 포스팅 하겠습니다.

HTTP 헤더 중 하나인 X-Forwarded-For를 이용하는 방법과 각 소프트웨어의 모듈을 이용하여 Client IP를 식별하는 방법 두 가지에 대해서 알아보겠습니다.


테스트 기본 세팅

해당 이미지를 더블 클릭하시면 큰 화면으로 이미지를 자세히 볼 수 있습니다.

저는 VPC 환경에서 테스트를 진행하였습니다.
(Classic도 동일한 방법으로 가능합니다.)

centos-7.8-64로 생성해주었습니다.
서버 생성 후 Apache를 설치합니다.

[root@manvscloud-web-pub-kr2 ~]# yum install httpd httpd-devel -y
[root@manvscloud-web-pub-kr2 ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@manvscloud-web-pub-kr2 ~]# systemctl start httpd

테스트 준비는 끝났습니다.
이제 LB가 없을 때, X-Forwarded-For를 사용할 때, 각 소프트웨어의 모듈을 사용할 때에 대해서 살펴보겠습니다.


Load Balancer가 없을 때

우선 Load Balancer가 없을 때 해당 서버로 접근 할 경우 정상적으로 Client IP가 찍힙니다.
(Client – Server)


Load Balancer를 추가했을 때

Application Load Balancer로 생성하였습니다.
index.jsp → index.html
tail -f /var/log/httpd/access_log

Load Balancer를 추가하게되면 위와 같이 Client IP가 아닌 LB의 사설 IP가 찍히게 됩니다.
(Client – LB – Server)

이제 LB가 있는 상태에서 Client IP를 볼 수 있도록 설정해보겠습니다.


X-Forwarded-For

[root@manvscloud-web-pub-kr2 html]# grep -n LogFormat /etc/httpd/conf/httpd.conf 
196:    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
197:    LogFormat "%h %l %u %t \"%r\" %>s %b" common
201:      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio

Apache의 LogFormat을 보면 현재 위와 같이 되어있습니다.
이 LogFormat을 조금 변경해줄 것입니다.

vi /etc/httpd/conf/httpd.conf 를 이용하여 196 라인에 LogFormat을 아래와 같이 변경 해주겠습니다.

    196     LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

기존 LogFormat 가장 앞부분에 %{X-Forwarded-For}i 을 추가해준 것입니다.
이를 추가해준 뒤에 Apache 재시작 1회 진행 후 다시 한 번 로그를 확인해보면 Client IP가 찍히게 됩니다.

웹 접속 시 Client IP가 추가된다.

이 설정은 Apache 뿐만 아니라 Nginx, Tomcat에서도 당연히 설정이 가능합니다.
아래 링크를 참고하면 좋을듯합니다.


Network Proxy Load Balancer

이제 Apache와 Nginx에 모듈을 추가하여 Client IP 식별하는 방법에 대해 알아볼 것입니다.

모듈을 설명하기 앞서 기존에 사용하던 ‘애플리케이션 로드밸런서’에서
‘네트워크 프록시 로드밸런서’로 변경해줄 것입니다.

LB 생성은 크게 다를 것이 없습니다.
다만 Target Group에서 조금 다르게 설정을 해줄 것입니다.

프로토콜은 PROXY_TCP로 해줍니다!
그리고 TargetGroup 설정에서 ProxyProtocol을 클릭해줍니다.

콘솔에서 해줄 작업은 이걸로 끝입니다. 이제 모듈을 추가하러 갑시다!


Apache Module

[root@manvscloud-web-pub-kr2 src]# apachectl -M | grep myfixip

Apache에서는 myfixip 모듈을 이용할 것입니다.
해당 모듈의 경우 기본 내장 모듈이 아니라 아래와 같이 추가해주어야합니다.

[root@manvscloud-web-pub-kr2 html]# cd /usr/local/src
[root@manvscloud-web-pub-kr2 src]# wget --no-check-certificate https://raw.githubusercontent.com/ggrandes/apache24-modules/master/mod_myfixip.c
[root@manvscloud-web-pub-kr2 src]# apxs -aic mod_myfixip.c 
[root@manvscloud-web-pub-kr2 src]# apachectl -M | grep myfixip
 myfixip_module (shared)

myfixip_module이 추가된 것을 확인할 수 있습니다.
이제 httpd.conf에 해당 모듈을 추가해주고 사용할 것입니다.

[root@manvscloud-web-pub-kr2 ~]# cat << EOF >> /etc/httpd/conf/httpd.conf
> LoadModule myfixip_module modules/mod_myfixip.so
> <IfModule mod_myfixip.c>
> RewriteIPResetHeader off
> RewriteIPAllow 10.0.0.0/16  
> </IfModule>
> EOF
[root@manvscloud-web-pub-kr2 ~]# systemctl restart httpd

RewriteIPAllow은 Load Balancer가 있는 대역을 추가해주면 됩니다.
위에서 추가한 Proxy LB로 접속하게 되면 이제 아래와 같이 Log가 남습니다.

Apache myfixip

정말 깔끔하게 Client IP가 보이고 있습니다.
이제 Apache와 함께 많이 사용되고 있는 Nginx에서 설정을 해보겠습니다.


Nginx Module

우선 Nginx는 아래 내용을 참고하면 간단하게 설치가 가능합니다.

[root@manvscloud-web-pub-kr2 ~]# vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud-web-pub-kr2 ~]# yum install nginx
[root@manvscloud-web-pub-kr2 ~]# systemctl start nginx

Nginx에서의 설정도 어렵지 않습니다.
Nginx에서는 realip module이 있는지 확인해주어야합니다.

nginx -V 2>&1 | grep 'http_realip_module'
해당 이미지와 같이 모듈이 존재한다면 준비는 완료되었습니다.

vi /etc/nginx/nginx.conf 로 nginx의 config파일을 아래와 같이 변경해줄 것입니다.

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

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


        proxy_set_header X-Real-IP         $proxy_protocol_addr;
        proxy_set_header X-Forwarded-For   $proxy_protocol_addr;

        server
        { 
                root    /usr/share/nginx/html;
                listen 80  proxy_protocol;
                set_real_ip_from 10.0.2.0/24;
                real_ip_header proxy_protocol;     
        }

기존 log_format은 주석처리하고 그 아래에 전부 새로 추가한 내용들입니다.

  1. $remote_addr$proxy_protocol_addr로 변경해줍니다.
  2. proxy_set_header을 추가해줍니다.
  3. proxy protocol과 real_ip 설정도 해줍니다.

설정이 끝난 뒤 nginx를 1회 재시작하고 로그를 확인해봅니다.

Apache와 동일하게 Nginx도 Proxy LB로 접속하면 Client IP가 그대로 남는 것을 확인할 수 있었습니다.

이로써 LOAD BALANCER 사용 시에도 웹서버 로그에서 CLIENT IP를 볼 수 있다는 것을 알 수 있습니다.
이 글을 읽으시는 분들께서도 해당 포스팅을 참고하여 서버에서 Client IP가 보이도록 설정해보시는 건 어떠신가요?

웹 로그에서 Client IP를 확인하는 일은 꽤 많은 것같습니다.
가끔 MaxClients 설정이 낮지않은데 MaxClients 수치보다 많은 프로세스로 인해 확인을 해보면 특정 IP가 ESTABLISHED와 CLOSE_WAIT 을 반복하여 대량의 CLOSE_WAIT를 남겨 MaxClients가 순식간에 늘어나는 것을 많이 보았습니다.

그 특정 IP를 log파일에서 여러 명령어와 조합하여 wc -l 로 뽑아내면 공격성 및 이상 접근으로 의심되는 접근을 빠르게 판단하고 차단 / 조치 할 수 있게되는 것 같습니다.

해당 포스팅은 여기서 마무리해보려 합니다.

긴 글 읽어주셔서 감사합니다.