引言
在網路環境中,有時候我們需要讓區域網路內的電腦存取外網,但是由於網路策略或其他原因,直接存取外網是不可行的。這時候,可以借助 Nginx 來搭建一個正向代理伺服器,實作區域網路內電腦透過 Nginx 轉發存取外網的需求。
在工作中我遇到了一個類似的情況:在公司網路中,由於管理要求,區域網路內的電腦不能直接存取外網。但是,工作上領導吩咐需要讓區域網路內的電腦能夠存取外網上的某個網站,這時候就需要用到正向代理。本文將介紹如何配置 Nginx 實作這一功能。
準備工作
首先,我們需要一台可以存取外網的伺服器,例如一台伺服器、電腦或者虛擬機器。確保該伺服器已經安裝了 Nginx,並且網路配置正確。
我這裏是有一台伺服器是可以正常存取外網的(IP:192.168.0.10),同時區域網路內的其他電腦也可以存取這台伺服器。
修改nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 正向代理配置內容
server {
listen 9000; # 監聽埠
server_name localhost;
set$url"proxy_server_doman_or_ip"; # 設定代理的網域名稱或IP變量,這裏替換成自己需要代理的網站
location / {
proxy_pass http://$url:8082; # 將請求轉發到由 $url 變量表示的地址。
}
}
}
重新開機nginx,開啟區域網路電腦測試存取:192.168.0.10:9000,網頁跳轉成功。不就是請求轉發嘛,so easy!
問題解決?如果這麽簡單我就不寫這篇文章了😄
果然第二天就出問題了,有同事反饋網站進不去了。我想不可能吧,一測試果然不行。果斷查閱了一下資料,找到問題原因:nginx在進行網域名稱轉發時會先把網域名稱解析成IP保存在記憶體中,後面的存取都是透過IP直接存取,如果目標網站的 IP 地址發生變化,我們的代理就會失效。
找到原因就好辦了,添加網域名稱解析功能嘛
網域名稱解析
為了解決 IP 地址變化的問題,我們可以使用網域名稱解析來動態獲取目標網站的 IP 地址。直接奉上完整配置,修改 Nginx 配置如下:
# 設定Nginx啟動一個工作行程,這是Nginx的一個核心設定,它決定了Nginx會使用多少個工作行程來處理客戶端請求。
worker_processes1;
# 配置定義了Nginx如何處理事件,例如連線請求,數據傳輸等
events {
worker_connections1024; # 定義了每個工作行程允許的最大並行連線數。
}
# HTTP模組的配置塊,包含了HTTP伺服器的一般配置
http {
include mime.types;
default_type application/octet-stream;
sendfileon;
keepalive_timeout65;
# 正向代理配置內容
server {
listen9000; # 監聽埠
server_name localhost;
# 設定DNS解析器的地址為8.8.8.8,並且設定了解析器的緩存時間為300秒(這樣每隔300s就會重新解析一次)。ipv6=off 是關閉IPv6的解析支持。
resolver8.8.8.8 valid=300 ipv6=off;
resolver_timeout3s; # 設定解析DNS的超時時間為3秒
proxy_read_timeout60s;
proxy_send_timeout60s;
proxy_connect_timeout60s;
set$url"proxy_server_doman_or_ip"; # 設定代理的網域名稱或IP變量,這裏替換成自己需要代理的網站
location / {
proxy_pass http://$url:9000; # 將請求轉發到由 $url 變量表示的地址。9000是目標網站的埠。
proxy_buffers2564K; # 設定用於緩存後端響應的緩沖區大小為256個,每個大小為4K。
proxy_max_temp_file_size0; # 設定Nginx暫存響應數據的最大臨時檔大小為0,即不使用臨時檔。
proxy_cache_valid2003021m; # 針對狀態碼為200和302的響應,設定緩存有效期為1分鐘。
proxy_cache_valid3011h; # 針對狀態碼為301的響應,設定緩存有效期為1小時。
proxy_cache_valid any 1m; # 對於其他任何響應狀態碼,設定緩存有效期為1分鐘。
}
}
}
重新開機nginx,問題解決。到這裏,正向代理功能就實作了。如果只想實作正向代理功能看到這裏就可以了。後面是我在遇到問題時的一些偵錯經驗技巧!
轉發代理偵錯
我在實作代理後,發現正向代理響應的速度非常慢有時候需要一分鐘才能響應結果。但有時候又很快。就好奇為啥會這樣,為了方便偵錯和監控,我設定添加了Nginx 的存取日誌。
修改 Nginx 配置如下:
# 設定日誌記錄格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"''upstreamIP: $upstream_addr''upgrade: $http_upgrade';
# 正向代理配置內容
server {
listen 9000; # 監聽埠
server_name localhost;
# 設定DNS解析器的地址為8.8.8.8,並且設定了解析器的緩存時間為300秒(這樣每隔300s就會重新解析一次)。ipv6=off 是關閉IPv6的解析支持。
resolver 8.8.8.8 valid=300 ipv6=off;
resolver_timeout 3s; # 設定解析DNS的超時時間為3秒
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_connect_timeout 60s;
set$url"proxy_server_doman_or_ip"; # 設定代理的網域名稱或IP變量,這裏替換成自己需要代理的網站
location / {
proxy_pass http://$url:9000; # 將請求轉發到由 $url 變量表示的地址。9000是目標網站的埠。
proxy_buffers 256 4K;
proxy_max_temp_file_size 0;
proxy_cache_valid 200 302 1m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
access_log logs/proxy/access.log main; # 定義了存取日誌的路徑和格式。
error_log logs/proxy/error.log; # 定義了錯誤日誌的路徑
}
}
這樣,Nginx 將會在nginx計畫下的 logs/proxy/access.log 檔中記錄所有代理轉發日誌。
日誌資訊:
192.168.0.28 - - [27/Feb/2024:17:02:03 +0800] "GET /prod-api/system/todo/listAll?pageNum=1&pageSize=10&active=true HTTP/1.1" 200 64 "http://192.168.20.2:8082/user-task/todo" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0" "-"upstreamIP: 182.148.159.30:8082
192.168.0.28 - - [27/Feb/2024:17:02:03 +0800] "GET /prod-api/process/business/listAll?pageNum=1&pageSize=10&active=true HTTP/1.1" 200 979 "http://192.168.20.2:8082/user-task/todo" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0" "-"upstreamIP: 182.148.159.30:8082
192.168.0.28 - - [27/Feb/2024:17:02:06 +0800] "GET /prod-api/system/user/select HTTP/1.1" 499 0 "http://192.168.20.2:8082/login?redirect=/index" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0" "-"upstreamIP: 172.16.30.6:8082
透過日誌資訊可以看到,請求轉發後的upstreamIP有兩個不同的IP:182.148.159.30和172.16.30.6,說明請求被轉發到了兩個不同的IP,當請求IP為182.148.159.30時,響應正常;當請求IP為172.16.30.6時,響應失敗導致等待。
發現這個情況後,我也是很疑惑為啥會將網域名稱解析出兩個IP,第一反應是網域名稱解析錯誤,為了驗證我將DNS解析的伺服器換成了離我最近的四川電信伺服器:61.139.2.69,測試發現結果也是一樣的。雖然感覺解析是沒有問題的,保險起見我還是自己在網上透過解析網站測試了一下網域名稱解析的結果:結果顯示網域名稱確實繫結了兩個IP,一個是正常的一個是不行的。
然後我就聯系我們這個網域名稱對應網站的負責人,得出的結果就是他們確實繫結了兩個IP,有一個IP是繫結的內網IP,所以才導致外網請求時失效。
失敗的原因:nginx獲取解析後的IP是透過輪詢往IP轉發請求,如果輪詢到內網IP就會導致請求失敗。
解決辦法:
手動選擇IP地址:在Nginx配置中,你可以手動指定代理的目標IP地址,而不是使用解析出的IP地址。這樣可以避免將請求發送到內網IP。
使用網域名稱解析出的IP地址進行請求:你可以透過解析網域名稱獲取到的IP地址列表,然後使用一些方法(比如按照某種規則選擇IP地址)來保證請求不會發送到內網IP地址。
使用nginx的upstream模組進行負載均衡:透過upstream模組,你可以指定多個代理伺服器,然後使用一定的負載均衡策略,比如輪詢、權重等,來分配請求到不同的伺服器。在這裏,你可以手動配置upstream模組,指定外網IP,而不包括內網IP。
修改DNS設定:聯系網站負責人,修改網域名稱解析,只將外網IP繫結到網域名稱上,而不包括內網IP。
你們猜我最後咋解決的???
必須是第四條啊!!!
連結:https://www.cnblogs.com/lucky-fd/p/18069434
(版權歸原作者所有,侵刪)