요즘 서버가 불안정하면서 평소에 접해보지 못하던 희귀한 사례들을 만나게 되었습니다. 이중 NGINX의 443 포트 메모리가 이미 사용중이라서 NGINX 구동 불가하는 웹서버 에러를 만나 대처한 이야기를 풀어보고자 합니다.
이 현상은 멀웨어에 감염된 사이트를 지우고 다시 설치하는 가운데 만났습니다. 아마 해커가 교묘하게 사이트에서 얼웨어를 제거하면 웹서버가 작동되지 않토록 장난을 친것으로 추정하고 있는데요.
아무튼 멀웨어를 치료 후 서버를 다시 시작하면 시스템이 죽어버립니다.
그럴 겨우 보통 NGINX 웹서버를 체크 시 nginx -t 옵션을 사용해 점검합니다. 그러면 NGINX 세팅 중 문제 없는지를 체크해 이상이 없으면 OK 메세지를 보내는데요.
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Code language: PHP (php)
그리고나서 NGINX 웹서버를 다시 구동시키면 아무런 문제가 없이 작동합니다.
문제 상황
그런데 이 경우는 nginx -t에서는 아무런 문제가 없다가 service nginx restart 명령을 받아 NGINX 웹서버를 다시 가동하려면 에러 메세지를 내면서 NGINX 웹서버를 가동시키지 못합니다.
아래 메세지처럼 ‘systemctl status nginx.service’로 점검하라고 메세지 나오며, systemctl status nginx.service를 이용해 점검해보면
- NGINX 활성화할 수 없으며
- 80포트를 이미 사용하고 있다고 합니다.
# service nginx restart
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
# systemctl status nginx.service
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2020-07-02 16:37:00 KST; 28s ago
Docs: http://nginx.org/en/docs/
Process: 1109 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)
Jul 02 16:36:57 etrend systemd[1]: Starting nginx - high performance web server...
Jul 02 16:36:57 etrend nginx[1109]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in us>
Jul 02 16:36:58 etrend nginx[1109]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in us>
Jul 02 16:36:58 etrend nginx[1109]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in us>
Jul 02 16:36:59 etrend nginx[1109]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in us>
Jul 02 16:36:59 etrend nginx[1109]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in us>
Jul 02 16:37:00 etrend nginx[1109]: nginx: [emerg] still could not bind()
Jul 02 16:37:00 etrend systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Jul 02 16:37:00 etrend systemd[1]: nginx.service: Failed with result 'exit-code'.
Jul 02 16:37:00 etrend systemd[1]: Failed to start nginx - high performance web server
Code language: PHP (php)
net-tools로 원인 파악
그러면 누가 이미 address를 사용하고 있는지 점검하기 위해 netstat를 점검해 봅니다.
먼저 net-tools을 설치하구요.
apt install net-tools
Code language: PHP (php)
다음으로 아래 명령어로 네트워크 상황을 점검해 봅니다.
netstat -tulpN
Code language: PHP (php)
그랬더니 아래와 같이 http로 apache2가 이미 사용하고 있다고 합니다. 여기는 NGINX 웹서버이므로 hhtps는 NGINX가 사용해야 정상이겠죠.
# netstat -tulpN
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 localhost:6010 0.0.0.0:* LISTEN 1185/sshd: root@pts
tcp 0 0 localhost:mysql 0.0.0.0:* LISTEN 958/mysqld
tcp 0 0 localhost:submission 0.0.0.0:* LISTEN 1315/sendmail: MTA:
tcp 0 0 0.0.0.0:***** 0.0.0.0:* LISTEN 687/sshd: /usr/sbin
tcp 0 0 localhost:domain 0.0.0.0:* LISTEN 585/systemd-resolve
tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN 1315/sendmail: MTA:
tcp6 0 0 localhost:6010 [::]:* LISTEN 1185/sshd: root@pts
tcp6 0 0 [::]:http [::]:* LISTEN 702/apache2
tcp6 0 0 [::]:***** [::]:* LISTEN 687/sshd: /usr/sbin
udp 0 0 localhost:domain 0.0.0.0:* 585/systemd-resolve
udp 0 0 45.77.96.212.vul:bootpc 0.0.0.0:*
Code language: PHP (php)
어떤 상황에서 나타나는가
어떤 상황에서 이러한 문제가 발생하는지 점검해 보았는데요.
확실한 것 중의 하나는 certbot 명령을 dry run 옵션과 같이 사용 시 반드시 이 문제가 나타납니다.
Let’s encrypt SSL 인증 갱신 명령 옵션에 –dry-run이 있습니다. 이는 SSL 인증 완료 시기가 아니라도 종료 상황을 만들어 적절하게 갱신이 되는지를 시뮬레이션할해 볼 수 있는데요.
/usr/bin/certbot renew --dry-run >> /var/log/letsencrypt/renew.log
Code language: PHP (php)
이 옵션을 사용해 certbot new 명령을 실행 결과입니다.
~# /usr/bin/certbot renew --dry-run >> /var/log/letsencrypt/renew.log
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for happist.com
http-01 challenge for www.happist.com
nginx: [error] invalid PID number "" in "/var/run/nginx.pid"
Waiting for verification..
Cleaning up challenges
Code language: PHP (php)
그리고 다시 nginx를 구동시키면 구동되지 않습니다. 그래서 systemctl status nginx.service 명령으로 상황을 파악해보면 위에서 소개한 것처럼 이미 address가 사용 중이라고 나옵니다.
~# systemctl status nginx.service
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sat 2020-08-08 12:49:38 KST; 3min 9s ago
Docs: http://nginx.org/en/docs/
Process: 2257 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)
Aug 08 12:49:37 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Aug 08 12:49:37 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Aug 08 12:49:37 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Aug 08 12:49:37 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Aug 08 12:49:38 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Aug 08 12:49:38 etrend nginx[2257]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Aug 08 12:49:38 etrend nginx[2257]: nginx: [emerg] still could not bind()
Aug 08 12:49:38 etrend systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Aug 08 12:49:38 etrend systemd[1]: nginx.service: Failed with result 'exit-code'.
Aug 08 12:49:38 etrend systemd[1]: Failed to start nginx - high performance web server.
Code language: PHP (php)
해결 방안
이 문제의 근본적인 해결 방안, 즉 이런 문제가 나타나지 않토록 만드는 방법은 아직 확인하지 못했습니다.
다만 임시로 nginx 웹서버에서 다른 프로그램이 address를 먼저 사용한다는 문제를 해결을 위해서는 대략 두가지 방법이 있습니다.
apache2 stop 명령
우분투 설치 시 기본으로 apache2가 설치되어 있기 때문에 이 apache2 stop 명령을 사용하면 이 문제가 일시적으로 해소됩니다.
sudo /etc/init.d/apache2 stop
sudo service nginx restart
Code language: PHP (php)
fuser -k 80/tcp 사용
저는 apache2를 없애버리면 이 문제가 해소될 것으로 보고 apache2를 삭데햌ㅆ는데요. 그럼에도 불구하고 이문제는 계속 발생했습니다. apache2가 이 문제 원인은 아니라는 것이죠.
아마 위에서 지적한 대로 SSL 인증 과정에서 80주소를 일부 어플리케이션이 사용하고 되돌려주지 않는 버그가 있는 것 같습니다.
apsche2가 없는 경우는 아래 명령을 사용합니다.
sudo fuser -k 80/tcp
Code language: PHP (php)
그러면 아래와 같이 80/tcp address를 kil합니다.
~# sudo fuser -k 80/tcp
80/tcp: 2240 2249
Code language: PHP (php)
그리고 nginx를 구동하면 제대로 작동합니다.
SSL 갱신 스크립트 개선
이런 문제를 반영하여 SSL 갱신 스크립트를 아래와 같이 변경합니다. nginx를 구동하기 전에 fuser -k 80/tcp 명령을 추가하는 것입니다.
/etc/init.d/nginx stop
/usr/bin/certbot renew --dry-run >> /var/log/letsencrypt/renew.log
fuser -k 80/tcp
/etc/init.d/nginx start
Code language: PHP (php)
새롭게 뉴스레터를 시작했습니다.
1️⃣ 주식 등 투자 정보 : 기업 분석, IB 투자의견 등 투자 관련 내용
..... 테슬라 실적 및 IB들의의 테슬라 투자의견
2️⃣ 사례 및 트렌드 : 사례연구와 트렌드 관련 괜찮은 내용
.....유튜브와 경쟁대신 구독 전환한 비디오 플래폼 비메오 사례