1. 소개
Nginx는 가장 인기 있는 서버 중 하나입니다. 빠르고 가벼우며 인터넷에서 가장 큰 사이트를 호스팅할 책임이 있습니다. Nginx는 로드 밸런서, 리버스 프록시, HTTP 캐시 등으로 자주 사용됩니다.
이 사용방법(예제)에서는 요청된 위치에 대한 순방향 프록시로 사용하는 방법을 배우는 데 중점을 둡니다.
2. 정방향 프록시에 대한 동기
프록시 서버는 클라이언트와 요청된 리소스의 호스트 사이에서 중개자 역할을 하는 엔터티입니다. 이는 트래픽이 목적지(호스트 서버)에 도달하기 위해 추가 시스템을 통과함을 의미합니다. 프록시는 클라이언트를 대신하여 요청을 계속하므로 호스트 서버가 요청을 수락하면 프록시의 IP만 볼 수 있습니다. 이에 비해 리버스 프록시는 웹 바로 앞에 위치하며 클라이언트에서 오는 요청을 올바른 웹 서버(여러 서버 네트워크 내부)로 라우팅합니다.
순방향 프록시 사용의 유일한 단점은 애플리케이션 수준에서 작동하므로 트래픽을 라우팅하려는 각 앱에 대해 프록시를 설정해야 한다는 것입니다.
정방향 프록시를 사용하는 일부 사용 사례는 다음과 같습니다.
- 위치 제한 서비스에 액세스하기 위해 IP 및 위치를 마스킹
- 인터넷의 특정 리소스에 연결해야 하는 격리된 내부 네트워크용
- 리소스를 절약하기 위해 거의 변경되지 않는 콘텐츠에 대해 특정 서버에 요청 캐싱
프록시 는 트래픽을 암호화하지 않는 반면 VPN은 안전하고 암호화된 터널을 통해 트래픽을 리디렉션합니다 .
3. Nginx로 정방향 프록시 구현
포워딩 프록시를 구현하기 위해 Nginx가 설치된 Linux 머신을 사용할 것입니다. 이 예제을 위해 Nginx가 설치된 상태로 실행 중인 Linux 배포판 서버와 함께 VirtualBox를 사용할 것입니다. 몇 년 동안 코너.
먼저 기본 Nginx 구성 파일을 찾고 서버 부분을 어노테이션 처리하여 보관된 복사본으로 저장합니다. 일반적으로 /etc/nginx/sites-enabled/default 에서 찾을 수 있습니다 .
# Default server configuration
#server {
#listen 80 default_server;
#listen [::]:80 default_server;
#root /var/www/html;
# Add index.php to the list if you are using PHP
#index index.html index.htm index.nginx-debian.html;
#server_name _;
#location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
#}
#}
다음으로 forward 라는 새 파일을 만들고 필요한 모든 구성을 추가하여 Nginx를 작동하는 forward 프록시로 전환해 보겠습니다 .
server {
listen 8888;
location / {
resolver 8.8.8.8;
proxy_pass http://$http_host$uri$is_args$args;
}
}
첫 번째 구성으로 'listen 8888;' – 우리는 기본적으로 이 포트로 가는 모든 요청이 다음 구성으로 처리되어야 한다고 서버에 알리고 있습니다. 위치 인수 는 특정 서버 세분화 블록 구성을 담당하고 기본적으로 특정 URI에 대한 요청을 처리하는 방법을 서버에 알려줍니다.
' resolver 8.8.8.8' 지시문은 업스트림 서버의 이름을 주소로 확인하는 데 사용해야 하는 네임서버를 지정합니다. 이 경우 8.8.8.8은 Google의 네임서버에 해당합니다.
$http_host 변수 는 원래 요청의 호스트를 포함하는 반면 $uri 는 도메인 또는 IP 뒤의 경로를 포함합니다. 마지막 두 변수 $is_args 및 $args 는 초기 요청에서 추가 인수를 확인하고 프록시 요청에 자동으로 추가합니다.
필요한 모든 구성을 업데이트한 후 적용하려면 nginx.service 를 다시 시작해야 합니다.
sudo systemctl restart nginx.service
4. 정방향 프록시 사용
앞에서 언급한 바와 같이 정방향 프록시는 애플리케이션 수준에서 작동하므로 자연스럽게 클라이언트에 따라 정방향 프록시를 구성할 수 있는 여러 가지 방법이 있습니다. 이 단계에서는 JavaScript로 간단한 클라이언트를 만들고 요청을 추적합니다.
시작하기 전에 최신 node.js 및 npm이 로컬 시스템에 설치되어 있는지 확인하십시오. 다음으로 클라이언트용 디렉터리와 파일을 만듭니다. 그에 따라 Proxy Test 디렉토리 와 proxytest.js 파일을 호출하겠습니다 .
다음으로 필요한 모든 라이브러리를 설치할 수 있도록 NPM의 package.json 을 초기화해야 합니다. 프로젝트 디렉터리 내부의 터미널에서 npm init 명령을 실행하여 이 작업을 수행합니다 .
npm init
리포지토리를 성공적으로 초기화한 후 프록시 구성으로 사용자 지정 요청을 빌드하는 데 사용할 요청 라이브러리를 설치해야 합니다.
npm install request
마지막으로 IDE를 열고 아래 코드를 proxytest.js 파일에 붙여넣습니다.
var request = require('request');
request({
'url':'http://www.google.com/',
'method': "GET",
'proxy':'http://192.168.100.40:8888'
},function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
})
이제 이 코드 스니펫을 실행해 보겠습니다.
node proxytest.js
한 걸음 뒤로 물러서서 각 라인을 살펴보겠습니다. 첫 번째 줄 은 나중에 사용할 요청 개체 로 라이브러리를 가져옵니다 .
요청 개체 내 에서 대상 서버의 URL, HTTP 메서드 및 프록시를 URL 및 포트 키 쌍으로 지정합니다. 콜백 함수 내에서 요청이 성공하면 Response body을 콘솔에 기록합니다.
다음으로 Nginx의 디버그 로그를 살펴보겠습니다.
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: "http://"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script var: "www.google.com"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script var: "/"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script var: ""
2022/02/20 13:46:13 [debug] 1790#1790: *1 http init upstream, client timer: 0
2022/02/20 13:46:13 [debug] 1790#1790: *1 epoll add event: fd:7 op:3 ev:80002005
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: "Host"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script var: "www.google.com"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: "Connection"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: "close"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: ""
2022/02/20 13:46:13 [debug] 1790#1790: *1 http script copy: ""
2022/02/20 13:46:13 [debug] 1790#1790: *1 http proxy header:
"GET / HTTP/1.0
Host: www.google.com
Connection: close
"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http cleanup add: 0000560CE3CF5E30
2022/02/20 13:46:13 [debug] 1790#1790: *1 http finalize request: -4, "/?" a:1, c:2
2022/02/20 13:46:13 [debug] 1790#1790: *1 http request count:2 blk:0
2022/02/20 13:46:13 [debug] 1790#1790: *1 http run request: "/?"
2022/02/20 13:46:13 [debug] 1790#1790: *1 http upstream check client, write event:1, "/"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http upstream resolve: "/?"
2022/02/20 13:46:14 [debug] 1790#1790: *1 name was resolved to 142.250.184.100
2022/02/20 13:46:14 [debug] 1790#1790: *1 name was resolved to 2a00:1450:4002:406::2004
2022/02/20 13:46:14 [debug] 1790#1790: *1 get rr peer, try: 2
2022/02/20 13:46:14 [debug] 1790#1790: *1 get rr peer, current: 0000560CE3CF5EB8 -1
2022/02/20 13:46:14 [debug] 1790#1790: *1 stream socket 12
2022/02/20 13:46:14 [debug] 1790#1790: *1 epoll add connection: fd:12 ev:80002005
2022/02/20 13:46:14 [debug] 1790#1790: *1 connect to 142.250.184.100:80, fd:12 #3
보시다시피 초기 요청은 프록시를 통과합니다. 그 직후 프록시 서버는 대상 리소스에 대한 초기 요청의 모든 데이터를 포함하는 새 요청을 시작합니다. 그런 다음 리소스에서 응답을 받아 클라이언트에 반환합니다.
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy status 200 "200 OK"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Date: Sun, 20 Feb 2022 12:46:15 GMT"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Expires: -1"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Cache-Control: private, max-age=0"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Content-Type: text/html; charset=ISO-8859-1"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info.""
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Server: gws"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "X-XSS-Protection: 0"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "X-Frame-Options: SAMEORIGIN"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Set-Cookie: 1P_JAR=2022-02-20-12; expires=Tue, 22-Mar-2022 12:46:15 GMT; path=/; domain=.google.com; Secure"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Set-Cookie: NID=511=IkyJTmMt6I2b3fHpGNUwdfCkv1q9cjzyeUaxC-cxMZWcbmSi4sVlRlwXJUTRA9ujqQnK2v6DNyhitL3zPRSf7RSIHDCv8aYcUD7jp3vX4sE7ZkiprAWmJo9FlnUJtV9H0IzOFyPck15Jfs0zb1VeOMOjKZk0BZ0XRQ3gNptMOl8; expires=Mon, 22-Aug-2022 12:46:15 GMT; path=/; domain=.google.com; HttpOnly"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Accept-Ranges: none"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header: "Vary: Accept-Encoding"
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy header done
2022/02/20 13:46:14 [debug] 1790#1790: *1 xslt filter header
2022/02/20 13:46:14 [debug] 1790#1790: *1 HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 20 Feb 2022 12:46:14 GMT
Content-Type: text/html; charset=ISO-8859-1
Transfer-Encoding: chunked
Connection: close
Expires: -1
Cache-Control: private, max-age=0
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Set-Cookie: 1P_JAR=2022-02-20-12; expires=Tue, 22-Mar-2022 12:46:15 GMT; path=/; domain=.google.com; Secure
Set-Cookie: NID=511=IkyJTmMt6I2b3fHpGNUwdfCkv1q9cjzyeUaxC-cxMZWcbmSi4sVlRlwXJUTRA9ujqQnK2v6DNyhitL3zPRSf7RSIHDCv8aYcUD7jp3vX4sE7ZkiprAWmJo9FlnUJtV9H0IzOFyPck15Jfs0zb1VeOMOjKZk0BZ0XRQ3gNptMOl8; expires=Mon, 22-Aug-2022 12:46:15 GMT; path=/; domain=.google.com; HttpOnly
Accept-Ranges: none
Vary: Accept-Encoding
2022/02/20 13:46:14 [debug] 1790#1790: *1 write new buf t:1 f:0 0000560CE3CF7AD0, pos 0000560CE3CF7AD0, size: 760 file: 0, size: 0
2022/02/20 13:46:14 [debug] 1790#1790: *1 http write filter: l:0 f:0 s:760
2022/02/20 13:46:14 [debug] 1790#1790: *1 http cacheable: 0
2022/02/20 13:46:14 [debug] 1790#1790: *1 http proxy filter init s:200 h:0 c:0 l:-1
2022/02/20 13:46:14 [debug] 1790#1790: *1 http upstream process upstream
요청이 대상으로 성공적으로 전송되면 요청이 수락되고 응답이 성공적으로 반환되었음을 의미하는 "200 OK" 응답이 로그에 표시됩니다. 로그에서 응답이 반환한 모든 HTTP 헤더가 줄별로 나열되어 있는 것도 볼 수 있습니다. 대상 서버가 반환하는 모든 HTTP 헤더는 프록시 반환 개체에 자동으로 추가됩니다.
5. 결론
이 예제에서는 Nginx 서버를 사용하여 쉽고 가벼운 순방향 프록시를 설정하는 방법을 배웠습니다. 순방향 프록시와 VPN의 중요한 차이점을 배웠습니다. 마지막으로 JavaScript 기반 클라이언트를 새로 만든 정방향 프록시에 연결하는 방법도 배웠습니다.
전체 소스 코드는 GitHub 에서 찾을 수 있습니다 .