1. 程式人生 > >Nginx配置二級目錄/路徑 映射不同的反向代理和規避IP+端口訪問

Nginx配置二級目錄/路徑 映射不同的反向代理和規避IP+端口訪問

nbsp ade 直接 窗口 返回 ngs remote 測試 span

當配置Nginx來映射不同的服務器 可以通過二級路徑來反向代理 來解決一個外網端口實現多個服務訪問。

配置如下:

server {
        listen 80;
        server_name demo.domain.com;
        #通過訪問service二級目錄來訪問後臺
    location /service/ {
            #DemoBackend1後面的斜杠是一個關鍵,沒有斜杠的話就會傳遞service到後端節點導致404
            proxy_pass      http://backend1/;
            proxy_redirect  off;
            proxy_set_header Host $host;
            proxy_set_header X
-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #其他路徑默認訪問前臺網站 location / { proxy_pass http://backend2; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X
-Forwarded-For $proxy_add_x_forwarded_for; } } #簡單的負載均衡節點配置 upstream backend1 { server 192.168.1.1; server 192.168.1.2; ip_hash; } upstream backend2 { server 192.168.2.1; server 192.168.2.2; ip_hash; }

對於規避IP+端口訪問,可能粗略一看,還沒理解是個啥意思吧!

其實就是現在業界流行的一種防DNS汙染的解決方案之一:

手機APP裏面除了通過域名來獲取數據,還會額外嵌入一些備用的IP。APP在獲取數據時,會先通過域名向服務器發起一個簡單的校驗請求,如果得到的不是預期數據,說明該網絡環境下的DNS已被汙染,比如被運營商劫持,請求A內容卻給你展示B內容!這時候,APP將會啟動備用預案,通過IP的方式來請求數據!很明顯,這個做法可以有效避免惡心的DNS劫持了(看完這段是不是有所收獲呢?)。

做法很簡單,就是在APP中集成多個IP和端口作為備用的訪問途徑。

當開發GG找到我,提出的需求是:

需要實現公網IP+端口來訪問,比如郵件API使用 http://192.168.1.10:125

Ps:公網服務器是多線的,那麽就有多個IP,本文假設電信是192.168.1.10,聯通是192.168.2.10,移動是192.168.3.10等

說白了就是要用端口來區分不同的API,此時如果我不深究,順手可能會寫出如下配置:

Shell
#API1
server {
        listen 125;
        server_name 192.168.1.10 192.168.2.10 192.168.3.10;
        location / {
            proxy_pass      http://DemoBackend;
            proxy_redirect  off;
            proxy_set_header   Host  api1.domain.com;
            proxy_set_header   X-Real-IP   $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}
#API2
server {
        listen 126;
        server_name 192.168.1.1 192.168.2.1 192.168.3.1;
        location / {
            proxy_pass      http://DemoBackend;
            proxy_redirect  off;
            proxy_set_header   Host  api2.domain.com;
            proxy_set_header   X-Real-IP   $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}
##API n等等....

粗略一看,確實是可以實現開發GG的要求啊!再仔細一想,你會發現如此做法會開放越來越多的端口!運維成本以及辨識度低還只是其次,咱說好的安全第一呢?

經過思考和測試,我寫出的最終配置如下:

Shell
#新增的IP映射配置
server {
        listen 80;
        server_name 192.168.1.10 192.168.2.10 192.168.3.10;
        location /mail_api/ {
            proxy_pass      http://DemoBackend/; #後面的斜杠不能少,作用是不往後端傳遞/mail-api 這個路徑
            proxy_redirect  off;
            proxy_set_header  Host  mailapi.domain.com; #傳遞不同的host給後方節點,實現IP和域名均可以訪問
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        location /other_api1/ {
            proxy_pass      http://DemoBackend/; 
            proxy_redirect  off;
            proxy_set_header  Host  otherapi1.domain.com;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        #還可以添加更多映射,通過不同的路徑來映射不同的API,最後對於直接訪問IP則返回403,防網絡上的掃碼探測
    location / {
        return 403;
    }
}

#原有的域名映射
server {
     listen 80;
     server_name mailapi.domain.com;
     location / {
        proxy_pass      http://DemoBackend;
            proxy_redirect  off;
            proxy_set_header  Host  $host;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
server {
     listen 80;
     server_name otherapi1.domain.com;
     location / {
        proxy_pass      http://DemoBackend;
            proxy_redirect  off;
            proxy_set_header  Host  $host;
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
#簡單的節點配置(當這些API都用到同一個Backend時,上述代碼中的proxy_set_header傳遞的host就起到了關鍵性作用!)
upstream DemoBackend {
     server 192.168.10.1;
     server 192.168.10.2;
     ip_hash;
 }

最終實現的效果就是:你要通過IP請求郵件API,只要請求 http://192.168.1.1/mail_api/ 即可,而不需要開放多余端口。而且,後續要新增更多API,只需要定義不同的二級路徑即可,這些二級路徑的辨識度可比端口要好得多!

Ps:正如代碼中的註釋,示例代碼只用了一個 DemoBackend 節點配置,為的是分享另一個小技巧:當後端節點承載了多個站點而且都是監聽80端口時(比如某些小公司同一個IIS服務器部署了N個站點),反向代理中的proxy_set_header參數,可以自定義傳遞一個host域名給後端節點,從而正確響應預期內容!

這段解釋有點無力,還是拿實際例子舉例吧!

我之前供職的公司節點用的是IIS服務器,前端用Nginx反向代理,IIS服務器上有多個站點,站點之間部分會通過 rewrite 規則聯系起來。

打個比方:比如A網站有個專題內容(www.a.com/zt/)是通過IIS偽靜態映射到了B網站(content.b.com)。也就是訪問到http://www.a.com/zt/,其實最後是通過A網站映射到了B網站上面。

後來發現IIS有個偽靜態BUG,會經常奔潰,就要我用前端的Nginx來實現直接映射,而不再走IIS的A網站中轉。

那麽這個需求就正好用到了 proxy_set_header 技巧,一看就懂:

Shell
server {
     listen 80;
     server_name www.a.com;
     location /zt/ {
        proxy_pass      http://ABackend; #都是相同的節點,此示例代碼我就不寫upstream了
            proxy_redirect  off;
            proxy_set_header  Host www.b.com; #這裏就是關鍵性作用,傳遞b域名給後端IIS
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

#upstream略..

很明顯,通過傳遞自定義域名,就可以實現通過A網站訪問Nginx,返回B網站內容,和反向代理谷歌的原理是一致的。

當然,上文為了實現 IP 和域名都可以訪問,這個proxy_set_header 設置也是必須的。說白了就是在反代過程中,對後端服務器偽裝(傳遞)了一個自定域名,讓後端響應該域名預期內容。

本文分享的經驗,其實比較簡單,主要就是通過不同路徑來反代不同的目標。估計很多大拿早就用爛了吧!不過值得註意的是,通過自定義路徑反代,需要註意 proxy_pass 參數後面是否需要斜杠,避免將自定義的路徑傳遞到後端節點,導致訪問404!

Nginx配置二級目錄/路徑 映射不同的反向代理和規避IP+端口訪問