엔진엑스

히든위키 코리아
필독 유닠스 계열 저작물, 성인물, 도박 프로그래밍 웹 써버 보안 대화방
필독 사항 프로젴트 트라이던트 표면 웹 싸이트 제작 파이썬 리눅스 마스터 대화방 2019년
위키 편집 리넠스 마약, 아청물, 해킹 웹 프로그래밍 웹 싸이트 보안
위키 문서 작성법 우분투 다크넽 싸이트 제작 쟁고우 정보 보안 기사

개요

엔진엑스(nginx)는 러시아 개발자 Igor Sysoev가 혼자서 만든 프로젝트이지만, 메모리와 성능이 좋아 입소문으로 많이 사람들이 알게 되었다. 2002년부터 시작되어 최근 사용하는 곳이 급속히 증가하고 있다.

https://nginx.org


특히 nginx는 http://wordpress.com 에 적용되면서 많이 유명해졌다. 현재 Nginx를 쓰는 유명한 곳으로는 페이스북, Netflix, WordPress.com, GitHub, 사운드클라우드, Zynga, Sourceforge 등이 있으며, 한국에서는 네이버 첫페이지, 백과사전, 일베저장소, 엔하위키 미러,카카오톡 공지사항 서버, XpressEngine 공식 홈페이지등이 있다.

http://vbtechsupport.com/wp-content/uploads/2012/01/activewebsites_rank.png

nginx 는 비동기(async) 이벤트 기반(ioctl, send, recv, epoll)으로 만들어졌고, Apache Http 서버는 프로세스 또는 쓰레드를 태생으로 만들어졌다.

따라서, 더 적은 자원으로 더 빠르게 데이터를 서비스 할 수 있다.


요즘엔 아파치(Apache)보다 엔진엑스(nginx)를 많이 쓴다.


아파치는 server-status 모듈이 설치되어 활성화되어 있고, directory listing 기능도 켜져있는 등 익명 써버를 운영하려는 사람에게는 정체를 들킬 위험이 많은 모듈이나 옵션이 기본적으로 활성화되어 있다. 일일이 다 꺼줘도되지만 이런 익명 보안 설정을 잘 모르는 사람에게는 아파치가 위험할 수도 있다. 아무 설정 안 하고 쓸거라면, 차라리 이런 기능들이 기본적으로 포함이 안 되어 있거나 꺼져있는 엔진엑스가 안전하다.

성능

성능은 접속자가 어느 정도 이상 되고 다양한 사이트가 운영되면 차이가 많이 난다. 동접자가 많을수록 체감할수 있다 물론 설정을 시스템에 맞게 잘 해 주셔야 효과가 극대화 되겠다. 서버가 리눅스일 경우, 그리고 멀티코어일 경우 엔진엑스와 아파치의 차이가 많이 난다. 윈도우용 Nginx는 native win32 api를 이용하며, select() 연결만 사용하기 때문에 향상된 성능을 기대하기는 어렵다. 이외의 몇몇 제약 때문에 아직 베타버전으로 간주된다. http://nginx.org/en/docs/windows.html 를 참고한다.

한국에서 엔진엑스를 많이 안쓰는 이유는 아직 정형화된 한글 문서들이 없기 때문이다. 호스팅 서비스의 경우 rewrite 관련 부분을 사용하는 호스팅 사용자가 많은 경우 상당히 귀찮아 질 수 있다.

보통 접속자가 많은 사이트 (토렌트, 유머 등등) 인 경우 엔진엑스를 많이 쓰고 있는 추세이다. 성능을 원하면 Nginx로 셋팅하자.


http://stackoverflow.com/questions/14983276/php-processing-speed-apache-2-4-mpm-prefork-mod-php-5-4-vs-nginx-1-2-x-php-fpm-5

아파치 2.4와의 비교


엔진엑스를 프론트 엔드(front-end)에서 프록시로 쓰고 CSS, 이미지, 자바스크맆트 등의 정적인 컨텐츠를 처리하고 하고, PHP 프로세스는 백 엔드(back-end)의 아파치에 맡기는 방식으로도 쓴다.


nginx는 최대한 system call을 적게 하고 비동기 이벤트 처리를 통해서 높은 성능이 있다는 큰 장점과 함께 백엔드와 ajp 통신이 어렵고, 모듈 개발이 어려우며, Apache Http 서버처럼 다양한 모듈이 없다는 단점이 있다.

Apache와 기본 구조 비교

Apache Http 서버는 요청 하나당 프로세스(뜨는 쓰레드)가 처리하는 구조이다 보니, 만약 Apache Http 서버의 프로세스가 blocking(DB나 파일)이 되면 요청을 계속 처리하지 못하고 처리 완료때까지 대기하는 일이 생긴다. 그래서 Timeout이나 Keep Alive 체크를 정말 잘써야 하는 이슈가 생기게 되었다.

또한 MaxClient의 수치를 높여 dos 공격에 대해서 조금이라도 막을 수 있는 형태를 취하게 된다. 따라서 프로세스(또는 쓰레드) 메모리를 많이 할당/해제하는 상황이 생길 수 있다.

nginx는 쓰레드를 적게 사용하는 구조이다. 또한 쓰레드를 적게 쓰다보니 쓰레드당 할당되는 메모리도 적게 되면서 메모리도 적게 사용되는 구조가 된다. 하나의 쓰레드에서 이벤트를 처리하다 보니 blocking이 되는 일이 없는 셈이 된다. 또한 쓰레드를 적게 쓴 다는 것은 context swithing 비용도 적게 되기 때문에 cpu의 소모도 상대적으로 작게 된다. 하나의 프로세서는 하나의 쓰레드처럼 사용하여 적은 worker에서 동작이 된다. 다만 많은 요청을 처리하기 위해서 client 개수는 늘릴 필요는 있다.


http://nbonvin.wordpress.com/2011/03/24/serving-small-static-files-which-server-to-use/

Nginx 관련한 성능 테스트한 자료

설치

우분투에서 패키지를 이용해 설치하면된다. 우선 터미널에서 ssh가상 사설 써버(VPS)에 접속하여

apache2 -v

아파치 설치 여부를 확인한다. 대부분 이미 설치되어있을 것이다.

apt purge apache*

로 아파치를 제거한다. Do you want to continue? [Y/n] 라고 물어보면 y를 입력한다.

apt install nginx

로 엔진엑스를 설치한다.

설정

토어(Tor) 사용을 위한 엔진엑스 설정은 아파치(Apache)와 거의 동일하니 가상 전용 써버(VPS) 문서와 아파치 문서를 참고하기 바란다.


Tor 설치 후 정상 접속 여부는 다음과 같이 확인한다. 만약 hs1 디렉터리를 웹 사이트의 홈 디렉터리로 쓸 경우 /var/www/hs1 디렉터리에 아래 내용을 적은 index.html 파일을 저장한다.

     
         You are pretty...
     
     
         

I wanna fuck you!

그리고 Tor 브라우저로 자신의 웹 사이트의 onion 주소로 접속했을 때 위 index.html 파일의 내용이 정상적으로 보인다면 Tor 접속 설정에 성공한 것이다.


Nginx 설정은 /etc/nginx/nginx.conf, /etc/nginx/sites-available/default 에서 할 수 있다. 가상 전용 써버(VPS) 사용시 텍스트 편집기는 vim을 쓰면 된다.


/etc/nginx/sites-available/default 를 직접 쓰지말고 hs1 등 적당한 이름으로 복사한 후 사용한다. 그리고 그 파일을 /etc/nginx/sites-enabled/hs1 등의 위치로 심볼릭 링크를 걸어준다. sites-enabled 폴더에 원래 있던 default 파일은 지워준다.

홈 디렉터리 위치

엔진엑스의 기본 설정 파일은 /etc/nginx/sites-available/default 이지만 설정 파일을 복사 후 이름을 phpbb3로 바꿨다고 가정하자.

그리고 웹 싸이트의 루트 페이지를 html 폴더 대신 phpBB3 폴더를 쓴다고 한다면 /etc/nginx/sites-available/phpbb3 파일에서

root /var/www/html;

root /var/www/phpBB3;

로 바꿔준다.

인덱스 페이지 이름 변경

만약 피에이치피BB(phpBB)처럼 index.html 대신 index.php를 쓴다면

index index.html index.htm index.nginx-debian.html;

에서 index 바로 오른쪽에 index.php를 추가하여

index index.php index.html index.htm index.nginx-debian.html;

로 바꿔준다. 웹 써버가 왼쪽에 있는 파일 이름부터 찾아본다.

PHP용 MySQL 모듈

마리아DB 설치 후

apt install php-mysql

로 PHP용 MySQL 모듈을 설치한다.

nginx용 PHP 모듈

Nginx에서 PHP7(FastCGI)를 구동하기 위해서는 다음 명령으로 PHP-FPM (데몬 프로세스) 패키지를 설치해야 한다. 엔진엑스에서 피에이치피(PHP)를 쓰기 위해 터미널에 다음과 같이 입력한다.

apt install php-fpm

이렇게 하면 PHP 7 이상의 최신 버전이 설치된다. 아파치에서는 php-fpm 대신에 libapache2-mod-php를 설치한다.


PHP와 Nginx를 연동하기위해

apt install php-fpm 

으로 php-fpm 설치 후 엔진엑스 설정 파일에 다음 줄을 추가한다. /etc/nginx/sites-available/default 를 직접 쓰지말고 hs1 등 적당한 이름으로 복사한 후 사용한다.

       location / {
               # First attempt to serve request as file, then
               # as directory, then fall back to displaying a 404.
               try_files $uri $uri/ =404;
       }

       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
       #
       #location ~ \.php$ {
       #       include snippets/fastcgi-php.conf;
       #
       #       # With php7.0-cgi alone:
       #       fastcgi_pass 127.0.0.1:9000;
       #       # With php7.0-fpm:
       #       fastcgi_pass unix:/run/php/php7.0-fpm.sock;
       #}

       # deny access to .htaccess files, if Apache's document root
       # concurs with nginx's one
       #
       #location ~ /\.ht {
       #        deny all;
       #}
}

위와 같은 걸

       location / {
               # First attempt to serve request as file, then
               # as directory, then fall back to displaying a 404.
               try_files $uri $uri/ =404;
       }

       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
       #
       location ~ \.php$ {
                 include snippets/fastcgi-php.conf;
       #
       #       # With php7.0-cgi alone:
       #       fastcgi_pass 127.0.0.1:9000;
       #       # With php7.0-fpm:
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
       }

       # deny access to .htaccess files, if Apache's document root
       # concurs with nginx's one
       #
       location ~ /\.ht {
               deny all;
       }
}

와 같이 바꿔준다.


보안을 위해 /etc/php/7.0/fpm/php.ini 파일을 수정한다.

vim /etc/php/7.0/fpm/php.ini

으로 파일을 연 후

;cgi.fix_pathinfo=1

cgi.fix_pathinfo=0

로 바꾸면 된다. vim에서 특정 문자열 검색은

/cgi.fix

처럼 앞에 /를 붙여서 하면 된다. 이렇게 바꿔주지 않으면 PHP는 요청된 php 파일을 찾을 수 없는 경우 가장 비슷한 파일을 실행한다. 따라서 보안상 위험하다.

그리고

systemctl restart php7.0-fpm

/etc/init.d/php7.0-fpm restart

로 php7.0-fpm을 재시작한다.


php 연동이 잘 되었나 확인을 위해

<?php
phpinfo();

<?php
phpinfo();
?>

를 텍스트 편집기에 적은 후 info.php나 phpinfo.php 등의 이름으로 저장하고 웹 서버의 /var/www/html 등의 홈 디렉터리에 올린다. 그리고 웹 브라우저에 xxxxxxxxxxxxxxxx.onion/phpiinfo.php 등을 입력하여 확인해본다. php 버전 정보 등이 뜬다면 php 연동이 성공한 것이다.

보안상 자신의 서버 정보는 최대한 안 주는 것이 중요하니

rm phpinfo.php

명령어로 phpinfo.php 파일을 삭제한다.

특정 아이피 주소와 포트만 써버에 접속 허용

vim /etc/nginx/sites-available/default

해보면

server {
       listen 80 default_server;

으로 되어있다. 위 설정에서는 80번 포트로 웹 써버에 접속을 받는다. 그걸

server {
       listen 127.0.0.1:892 default_server;

처럼 바꾸면 127.0.0.1 IP 주소의 892번 포트로만 접속을 받는다.

웹 싸이트 루트 디렉터리 소유자 변경

웹 싸이트 루트 디렉터리 소유자와 소유 그룹을 root에서 다른 것으로 바꿔준다. 우분투데비안 계열의 경우 아파치엔진엑스 상관없이 www-data로 바꿔주면 된다. 예를 들어, 웹 싸이트 루트 디렉터리가 /var/www/phpBB3 일 경우

chown -R www-data:www-data /var/www/phpBB3

와 같이 실행한다. -R은 하위 폴더와 파일까지 모두 바꾸라는 의미이다. :의 왼쪽은 새로운 소유자, 오른쪽은 소유 그룹이다.

그리고 소유 권한이 적절하지 않으면 권한도 바꿔준다.

ll /var/www/phpBB3

해서 권한을 확인한다. 755가 아니면

chmod -R 755 /var/www/phpBB3

로 755로 바꿔준다.

Nginx 가상 호스트 설정

nano /etc/nginx/sites-available/default


가상호스트 설정을 연다. 그런 다음 전부 지워버리고 아래에 있는 내용을 복붙하고 저장하라.


server { 
listen 80; 
listen 443 ssl http2;
server_tokens off;
server_name (사이트 도메인 또는 IP 주소);
root /var/www/html/(CMS가 설치된 폴더); 
index index.php index.html; 
location / { 
try_files $uri $uri/ =404; 
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ /\.ht {
deny all;
}
# PHP FastCGI Process Manager
location ~ \.php$ { 
include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.1-fpm.sock; 
}
# restore real ip address from CF
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
real_ip_header CF-Connecting-IP;
}


괄호친 부분은 알아서 넣어라.


service nginx reload


NGINX reload.


이게 안된다면 https://www.howtoforge.com/tutorial/installing-nginx-with-php7-fpm-and-mysql-on-ubuntu-16.04-lts-lemp/ 를 참조. 다만 PHP 버전이 7.0이다.


Nginx 튜닝 팁 http://kwonnam.pe.kr/wiki/nginx/performance

Nginx 보안 팁 https://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html

fpm unix socket 연결

/etc/php5/fpm/pool.d/www.conf 수정

Look for the line listen = 127.0.0.1:9000 and change it to something like listen = /var/run/php5-fpm.sock. After doing so, restart PHP FPM:

  sudo service php5-fpm restart


 sudo service nginx restart

소켓 연결 에러

유닉스소켓 연결이 조금 더 빠르기는 하지만 TCP/IP 만큼 Scalable 하지는 않다. 일일 방문자가 만명 수준이 본 사이트(http://openwiki.kr) 에서도 유닉스 소켓 연결로 설정 후 종종 php가 연결이 끊기는 경우 (갑자기 사이트 먹통, nginx 와 php 재시작 후 살아남)가 생겼었다. 이를 다시 TCP연결로 복구한 뒤 해결되었다.

이런 경우 nginx가 502 에러를 뿜는다고 하는데, 그냥 먹통이 되기도 한다. 소켓 세팅을 만지거나 그냥 TCP/IP 로 돌아가면 된다.

In your fastcgi conf change:

   fastcgi_pass unix:/var/run/php5-fpm.sock;

to:

   fastcgi_pass 127.0.0.1:9000;


http://IP주소 로 접속해본다.

|기본 자료 폴더|/usr/share/nginx/www| |기본 디먼|www-data| |로그|/var/log/nginx/error.log| |로그|/var/log/nginx/access.log|

Rewrite

  http://당신의도메인/test.php?id=$1 ㅡ>  http://당신의도메인/$1
  rewrite ^/([a-zA-Z0-9_]+)$ /test.php?id=$1 last;
 * [rewrite 설명]
 * [-> Nginx 변환기]
 * [& bad]


 * last vs rewrite 
   *      Okay, so "break", means "if regexp matches the request, then rewrite  the request and then stop right here and serve the request as being a  static file". .. and then stop right here (in this location) and serve the request by the location's handler (static/proxy/fastcgi/etc)
   *  "last" means "if regexp matches the request then rewrite the request,  then do not move on to any subsequent rewriting rule, but now try to  match the request with a location in the config file"

서브도메인

<file>server { server_name m.openwiki.kr;

  1. return 301 $scheme://openwiki.kr$request_uri;
      rewrite ^(.*) http://openwiki.kr$1 permanent;

}</file>

url_redirect 참조.

핫링크막기

<file>

location ~ \.(gif|png|jpg|jpeg|JPG|GIF|JPEG|PNG)$ {

   valid_referers none blocked 
        yourwebsitewithcoolcontent.com 
        *.yourwebsitewithcoolcontent.com;
       if ($invalid_referer) {
           rewrite \.(gif|png|jpg|jpeg|JPG|GIF|JPEG|PNG)$
                      http://cfile10.uf.tistory.com/image/2618E03B516F888815E0BC 
           redirect;
       }

} </file>

Dokuwiki

도메인루트 & try_files 사용


<file> server {

       listen   80;
       root /home/www/wiki;
       server_name vaslor.net;
       location / {
               try_files $uri $uri/ @dk;
               rewrite ^/$ /doku.php last;
       }
       location @dk {
               rewrite ^/(.*) /doku.php?id=$1 last;
       }
       rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last;
       rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last;
       rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last;
       include common.conf;

} </file>


https://www.dokuwiki.org/rewrite?&#nginx 참고

Expire

<file>

       # 브라우져 캐쉬 세팅
       location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
               expires 65d;
                access_log off;
       }

</file>

htaccess

보안을 위하여 아파치의 htaccess를 감춘다. <file>

       location ~ /\.ht {
               deny all;
       }

</file>

Compression

/etc/nginx/nginx.conf

http section <file>


  1. enable gzip compression

gzip on; gzip_min_length 1100; gzip_buffers 4 32k; gzip_types text/plain application/x-javascript text/xml text/css; gzip_vary on;

  1. end gzip configuration

</file>

domain

<file>

    1. Server Block one

server { server_name www.domain1.com; access_log logs/domain1.access.log main; root /var/www/domain_1; }

    1. Server Block two

server { server_name www.domain2.com; access_log logs/domain2.access.log main; root /var/www/domain_2; } </file>

subdomain

이런식이다.

<file>server {

       listen 80;
       root /var/www/test;
       index index.php;
       server_name test.vaslor.net;
       location / {
               try_files $uri $uri/ index.php;
       }
       include common.conf;

} </file>

redirect subdomain to port

<file> server {

   listen 80;
   server_name app.example.com;
   location / {
       proxy_pass http://localhost:8142;
   }   

} </file>

성가신 로그 끄기

<file conf>

  1. Avoids filling up the error logs with commonly requested files.
  2. Note that if you have a custom 404 page, the request may be logged anyway.

location = /robots.txt { log_not_found off; } location = /favicon.ico { log_not_found off; } location = /apple-touch-icon.png { log_not_found off; } location = /apple-touch-icon-precomposed.png { log_not_found off; } location = /apple-touch-icon-120x120.png { log_not_found off; } location = /apple-touch-icon-120x120-precomposed.png { log_not_found off; } </file>


접근 로그는 nginx.conf에서 설정하는 것이 편하다.

 access_log off;

엔진엑스 보안 설정

서버 버전 숨기기

웹 서버가 죽었다거나 해서 서버에 접속이 안 될 경우

502 Bad Gateway

nginx/1.10.3 (Ubuntu)

와 같이 웹 써버 소프트웨어 종류와 버전, 운영 체제 종류까지 뜬다. 보안상 좋지 않다. 최대한 많은 정보를 숨겨야 안전하다. /etc/nginx 디렉터리로 간 후

sudo vim nginx.conf

하여 nginx.conf 파일을 수정한다.

# server_tokens off;

가 보일 것이다. 앞의 #을 지워

server_tokens off;

와 같이 주석 처리를 해제한다. 그러면 이제 정상적으로 server_tokens 기능이 꺼진다. 만약 위 내용이 없으면

http { 

밑에 적어주면 된다.

이제

sudo service nginx reload

하여 엔진엑스를 다시 불러오면

502 Bad Gateway

nginx

와 같이 뜨는 것을 확인할 수 있다. 웹 써버의 종류만 뜨지, 버전이나 운영 체제 종류는 뜨지 않는다.

서버 정보 보기

아파치의 server-status와 비슷한 것을 보려면 엔진엑스에 HttpStubStatusModule 이 설치되어 있어야 한다. 터미널

nginx -V 2>&1 | grep -o with-http_stub_status_module

를 입력하여

with-http_stub_status_module

가 뜨면 설치가 되어있는 것이다.

그리고 /etc/nginx 폴더의 nginx.conf 파일이나 /etc/nginx/sites-available 폴더의 각 사이트 설정 파일의

server { 

} 

사이에

location /nginx_status {
    stub_status on;
    access_log   off;
    allow 1.1.1.1;
    deny all;
}

라는 내용을 적어주고

sudo service nginx reload

해준다음 http://example.com/nginx_status 로 접속하면 대략의 서버 운영 내역을 볼 수 있다. 참고로 1.1.1.1은 자신의 웹 써버의 IP 주소를 적어주고, example.com은 자신의 웹 싸이트의 도메인 네임을 적어준다.

https://easyengine.io/tutorials/nginx/status-page/

결론적으로 말하자면 엔진엑스에서는 아파치와 달리 자신이 직접 설정하지 않는 한, 단순 외부 접속으로는 서버 운영 정보의 세밀한 부분은 드러나지 않는 것 같다.


아파치 호환성

getallheaders()

getallheaders는 아파치의 헤더를 받아오는 것으로 nginx에서는 작동하지 않는다. 호환성을 위해 다음과 같은 함수를 만들어 쓰면 된다.

<file php> if (!function_exists('getallheaders')) {

   function getallheaders() 
   { 
          $headers = ; 
      foreach ($_SERVER as $name => $value) 
      { 
          if (substr($name, 0, 5) == 'HTTP_') 
          { 
              $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; 
          } 
      } 
      return $headers; 
   } 

} </file>

* 참고: [[1]]

참고

  * http://www.solanara.net/solanara/nginx 소개, 리버스프록시로 사용...
  * http://helloworld.naver.com/helloworld/192785 모듈개발
  * http://opentutorials.org/module/384/3462 소개, 설치