Nginx TCP Proxy 서버

zuckerfrei·2023년 6월 27일
0

nginx

목록 보기
1/2

DB 모니터링 솔루션 도입을 준비중이다.

솔루션의 구성을 대략 설명하자면 이렇다.
1) DB 메트릭을 받아서 관리하는 '수집 서버'
2) DB서버에 설치되어서 수집 서버에게 메트릭을 전달하는 '에이전트'

여기서 문제는 DB서버와 수집서버간의 직접 통신을 보안상 제한하고 있다는 것이다.
그래서 이 두 서버 사이에 proxy 서버를 놓고 통신을 중개하고자 한다.

이 솔루션은 tcp 프로토콜로 통신한다고 하며, 크게 리소스를 요구하지도 않을 것 같기에 가벼운 nginx를 선택했다.

1. Nginx 버전 종류

stable, legacy, mainline 3가지 종류가 존재

  • stable : 안정적이어서 운영에 적합 => 선택
  • legacy : 약간 오래된 버전
  • mainline : 가장 최신버전 그래서 버그 존재 가능 & 보안 취약점도 있을 듯

2. Nginx module

Nginx에는 stream 모듈과 http 모듈이 존재한다.

  1. stream 모듈

    • TCP, UDP 프로토콜에 대한 프록시 & 로드밸런싱
  2. http 모듈

    • HTTP 프로토콜에 대한 프록시 & 로드밸런싱

TCP proxy 서버를 구성하려면 stream 모듈을 사용하면 된다.

다만, 기본 레포지토리(yum, apt)에서 패키지로 설치하면 stream 모듈이 제공되지 않는다.
필요하다면 소스 코드를 직접 컴파일해서 설치해야 하며, 컴파일 할 때 --with-stream 옵션을 추가해야 한다.

참조 공식문서에 설명이 잘 되어있고, 구성이 아주 간단하다.

3. 설치

  • 컴파일 설치

    # nginx 1.24 stable version 
    [admin@test-b-srv ~]$ wget https://nginx.org/download/nginx-1.24.0.tar.gz
    --2023-06-26 11:15:27--  https://nginx.org/download/nginx-1.24.0.tar.gz
    Resolving nginx.org (nginx.org)... 3.125.197.172, 52.58.199.22, 2a05:d014:edb:5704::6, ...
    Connecting to nginx.org (nginx.org)|3.125.197.172|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 1112471 (1.1M) [application/octet-stream]
    Saving to: ‘nginx-1.24.0.tar.gz’
    
    100%[==================================================================================================>] 1,112,471    824KB/s   in 1.3s
    
    2023-06-26 11:15:30 (824 KB/s) - ‘nginx-1.24.0.tar.gz’ saved [1112471/1112471]
    
    
    [admin@test-b-srv ~]$ tar -zxvf nginx-1.24.0.tar.gz
    nginx-1.24.0/
    nginx-1.24.0/auto/
    ...
    
    
    [admin@test-b-srv nginx-1.24.0]$ ./configure --with-stream
    checking for OS
     + Linux 3.10.0-1160.83.1.el7.x86_64 x86_64
    checking for C compiler ... found
     + using GNU C compiler
     + gcc version: 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
    checking for gcc -pipe switch ... found
    checking for -Wl,-E switch ... found
    checking for gcc builtin atomic operations ... found
    ...
    Configuration summary
      + using system PCRE library
      + OpenSSL library is not used
      + using system zlib library
    
      nginx path prefix: "/usr/local/nginx"
      nginx binary file: "/usr/local/nginx/sbin/nginx"
      nginx modules path: "/usr/local/nginx/modules"
      nginx configuration prefix: "/usr/local/nginx/conf"
      nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
      nginx pid file: "/usr/local/nginx/logs/nginx.pid"
      nginx error log file: "/usr/local/nginx/logs/error.log"
      nginx http access log file: "/usr/local/nginx/logs/access.log"
      nginx http client request body temporary files: "client_body_temp"
      nginx http proxy temporary files: "proxy_temp"
      nginx http fastcgi temporary files: "fastcgi_temp"
      nginx http uwsgi temporary files: "uwsgi_temp"
      nginx http scgi temporary files: "scgi_temp"
    
    
    [admin@test-b-srv nginx-1.24.0]$ sudo make install
    make -f objs/Makefile install
    make[1]: Entering directory `/home/admin/nginx-1.24.0'
    cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g  -I src/core -I src/event -I src/event/modules -I src/os/unix -I o                                                         bjs \
            -o objs/src/core/nginx.o \
            src/core/nginx.c
    ...
    make[1]: Leaving directory '/home/admin/nginx-1.24.0'
    

  • nginx 서비스로 등록
    # nginx.service 파일 생성 
    # 경로 꼭 확인할 것
    # vi /etc/systemd/system/nginx.service
    ---
    [Unit]
    Description=nginx
    After=network.target
    
    [Service]
    Type=forking
    ExecStart=/usr/local/nginx/sbin/nginx
    ExecReload=/usr/local/nginx/sbin/nginx -s reload
    ExecStop=/usr/local/nginx/sbin/nginx -s stop
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    
    
    # 등록
    [root@test-b-srv system]# systemctl daemon-reload
    
    
    # 부팅시 자동 실행 설정
    [root@test-b-srv system]# systemctl enable --now nginx
    Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /etc/systemd/system/nginx.service.
    
    
    # 상태 확인
    [root@test-b-srv system]# systemctl status nginx
    ● nginx.service - nginx
       Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: disabled)
       Active: active (running) since Mon 2023-06-26 11:26:57 KST; 4s ago
      Process: 65069 ExecStart=/usr/local/nginx/sbin/nginx (code=exited, status=0/SUCCESS)
     Main PID: 65070 (nginx)
        Tasks: 2
       Memory: 676.0K
       CGroup: /system.slice/nginx.service
               ├─65070 nginx: master process /usr/local/nginx/sbin/nginx
               └─65071 nginx: worker process
    
    Jun 26 11:26:57 test-b-srv systemd[1]: Starting nginx...
    Jun 26 11:26:57 test-b-srv systemd[1]: Started nginx.
    

4. 테스트

4-1. telnet

telnet으로 타겟 tcp 포트가 열렸는지 확인

  • 테스트 구성도
  • server - a서버 211.xx.xx.aa
    python2 -m SimpleHTTPServer 6001
  • proxy - b서버 211.xx.xx.bb 참조
    # nginx 설치
    # nginx.conf 수정
    events {
    }
    
    stream {
        # target
        upstream test-a {
            server 211.xx.xx.aa:6001;
        }
    
        # tcp
        server {
            listen 6002;
            proxy_pass test-a;
            proxy_connect_timeout 1s;
        }
    }
  • client - c서버 211.xx.xx.cc
    # b서버의 tcp포트 오픈 체크 
    [root@test-c-srv ~]# telnet 211.xx.xx.bb 6002
    Trying 211.xx.xx.bb...
    Connected to 211.xx.xx.bb.
    Escape character is '^]'.

4-2 netcat

netcat : TCP 또는 UDP를 통해 데이터를 주고 받을 수 있는 유틸리티
참조

실제 데이터를 주고 받을 수 있는지 테스트


  • 테스트구성도
  • proxy - b서버 211.xx.xx.bb
    양방향 테스트를 위해 2개의 upstream 생성 (a → b → c, c→ b → a)

    nginx.conf

    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    events {
    }
    
    stream {
        # ----- c->b->a -----
        # target
        upstream test-a {
            server 211.xx.xx.aa:6001;
        }
    
        # tcp
        server {
            listen 6001;
            proxy_pass test-a;
            proxy_connect_timeout 1s;
        }
    
        # ------ a->b->c ------
        # target
        upstream test-c {
            server 211.xx.xx.cc:6003;
        }
    
        # tcp
        server {
            listen 6003;
            proxy_pass test-c;
            proxy_connect_timeout 1s;
        }
    }
  • server - a서버 211.xx.xx.aa

    6001번 포트를 열어놓는다

    [root@test-a-srv ~]# nc -l 6001

    client에서 데이터를 전송하면 아래처럼 실시간으로 확인할 수 있다.

    [root@test-a-srv ~]# nc -l 6001
    hi, I'm c
  • client - c서버 211.xx.xx.cc test.txt 라는 파일 생성
    [root@test-c-srv ~]# cat test.txt
    hi, I'm c
    프록시 서버로 전달
    [root@test-c-srv ~]# cat test.txt | nc 211.xx.xx.bb 6002


+ 기본 레포지토리(yum)로 nginx를 설치할 경우

stream 모듈을 포함하지 않은 nginx로 tcp proxy 서버를 구축하려는 경우 발생하는 에러

[root@test-b-srv nginx]# systemctl restart nginx.service
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.


[root@test-b-srv nginx]# systemctl status nginx.service
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Mon 2023-06-26 11:03:29 KST; 8s ago
  Process: 60128 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
  Process: 60126 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 15642 (code=exited, status=0/SUCCESS)

Jun 26 11:03:29 test-b-srv systemd[1]: Starting The nginx HTTP and reverse proxy server...
Jun 26 11:03:29 test-b-srv nginx[60128]: nginx: [emerg] unknown directive "stream" in /etc/nginx/nginx.conf:16
Jun 26 11:03:29 test-b-srv nginx[60128]: nginx: configuration file /etc/nginx/nginx.conf test failed
Jun 26 11:03:29 test-b-srv systemd[1]: nginx.service: control process exited, code=exited status=1
Jun 26 11:03:29 test-b-srv systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
Jun 26 11:03:29 test-b-srv systemd[1]: Unit nginx.service entered failed state.
Jun 26 11:03:29 test-b-srv systemd[1]: nginx.service failed.

nginx: [emerg] unknown directive "stream" : stream을 찾을 수 없다고 나온다. 소스코드 컴파일로 설치하자

profile
무설탕 음료를 좋아합니다

0개의 댓글