X-Forward-For 看破紅塵,代理 IP 無所遁形!

      網(wǎng)友投稿 1239 2025-04-01

      在開始了解 X-Forward-For 之前,我們先來假設(shè)一個場景。你是一名爬蟲工程師,現(xiàn)在要爬取目標(biāo)網(wǎng)站 xxx.com 上面的內(nèi)容。在編碼的時候,你發(fā)現(xiàn)單位時間內(nèi)請求頻率過高時會被限制,猜測應(yīng)該是目標(biāo)網(wǎng)站針對 IP 地址做了限制。現(xiàn)在你有兩種選擇:


      單機,用 IP 代理解決頻率高被限制的問題。

      多機,用分布式爬蟲解決單機 IP 被限制的問題。

      由于目標(biāo)網(wǎng)站只需要爬取一次,單機 + IP 代理這種組合的成本更低,所以你選擇了它。從 IP 代理服務(wù)商 xx 處購買了代理服務(wù)后,你進行了新一輪的測試,代碼片段 Forwarded-Test 為測試代碼。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      X-Forward-For 看破紅塵,代理 IP 無所遁形!

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      import requests

      # 請求地址

      targetUrl = "http://111.231.93.117/"

      # 代理服務(wù)器

      proxyHost = "220.185.128.170"

      proxyPort = "9999"

      proxyMeta = "http://%(host)s:%(port)s" % {

      "host": proxyHost,

      "port": proxyPort,

      }

      proxies = {

      "http": proxyMeta,

      }

      # 設(shè)定一個 Referer

      header = {

      "Referer": "http://www.sfhfpc.com",

      }

      resp = requests.get(targetUrl, proxies=proxies, headers=header)

      print(resp.status_code)

      print(resp.text)

      代碼片段 Forwarded-Test 代碼運行后,你發(fā)現(xiàn)你仍然被限制! 頓時感到頭大,于是在各大搜索引擎尋找相關(guān)資料,例如:

      ip 代理無效 識別 ip 代理 ip 代理被發(fā)現(xiàn)

      你發(fā)現(xiàn)很多文章中都提到一個東西 X-Forward-For,大家都說它能夠看破 IP 代理。 那么問題來了:

      X-Forward-For 到底是什么呢?

      為什么 X-Forward-For 能夠發(fā)現(xiàn)我們使用了 IP 代理

      它怎么能找到原始 IP 呢?

      有什么方法可以騙過 X-Forward-For 呢?

      帶著這些問題,我們就來研究一下 X-Forward-For。

      X-Forward-For 是什么

      X-Forward-For 跟 Referer 和 User-Agent 一樣,都是 HTTP 中的頭域。HTTP/1.1 的 RFC 文檔編號為 2616,在 2616 中并未提及 X-Forward-For,也就是說 HTTP/1.1 出現(xiàn)的時候 X-Forward-For 還沒出生。真正提出 X-Forward-For 的是 2014 年的 RFC7239(詳見 https://www.rfc-editor.org/rfc/rfc7239.txt),這時候 X-Forward-For 作為 HTTP 擴展出現(xiàn)。 RFC: 全稱 Request For Comments,是一系列以編號排定的文件。它收集了互聯(lián)網(wǎng)相關(guān)的協(xié)議信息,你可以抽象地將 RFC2616 理解為 HTTP/1.1 的協(xié)議規(guī)范。Websocket 協(xié)議規(guī)范的詳細(xì)解讀可參考《Python3 反爬蟲原理與繞過實戰(zhàn)》一書。 關(guān)于 X-Forward-For 的所有正確描述都寫在了 RFC7239 中,所有符合規(guī)范的 HTTP 也會遵守 RFC7239。當(dāng)然,你也可以選擇不遵守。 不遵守: 實際上,RFC 只是一種規(guī)范、約定,作為大家統(tǒng)一行徑的參考,并未強制實現(xiàn)。很多反爬蟲手段就是另辟蹊徑,采用了與 RFC 約定不同的策略,具體反爬蟲思路和案例可參考《Python3 反爬蟲原理與繞過實戰(zhàn)》一書。 RFC7239 很長,我們不必逐一閱讀。實際上跟我們相關(guān)的只有幾個部分,例如:

      1

      2

      1.Abstract

      7.5. Example Usage

      Abstract 是本文章的摘要,它描述了 RFC7239 的作用:

      This document defines an HTTP extension header field that allows proxy components to disclose information lost in the proxying process, for example, the originating IP address of a request or IP address of the proxy on the user-agent-facing interface. In a path of proxying components, this makes it possible to arrange it so that each subsequent component will have access to, for example, all IP addresses used in the chain of proxied HTTP requests. This document also specifies guidelines for a proxy administrator to anonymize the origin of a request.

      大體意思為本文的定義(擴展)了一個 HTTP 頭域,這個字段允許代理組件披露原始 IP 地址。 從這里我們了解到 X-Forward-For 的正向用途是便于服務(wù)端識別原始 IP,并根據(jù)原始 IP 作出動態(tài)處理。例如服務(wù)端按照 IP 地址進行負(fù)載均衡時,如果能夠看破 IP 代理,取得原始 IP 地址,那么就能夠作出有效的負(fù)載。否則有可能造成資源分配不均,導(dǎo)致假負(fù)載均衡的情況出現(xiàn)。 Example Usage 給出了 X-Forward-For 的使用示例:

      A request from a client with IP address 192.0.2.43 passes through a proxy with IP address 198.51.100.17, then through another proxy with IP address 203.0.113.60 before reaching an origin server. This could, for example, be an office client behind a corporate malware filter talking to a origin server through a reverse proxy. o The HTTP request between the client and the first proxy has no “Forwarded” header field. o The HTTP request between the first and second proxy has a “Forwarded: for=192.0.2.43” header field. o The HTTP request between the second proxy and the origin server has a “Forwarded: for=192.0.2.43, for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com” header field.

      假設(shè)原始 IP 為 192.0.2.43,它的請求使用了地址為 198.51.100.17 的代理,在到達(dá)目標(biāo)服務(wù)器 203.0.113.60 之前還使用了另外一個代理(文章假設(shè)另外一個代理為 222.111.222.111)。 這種情況下

      客戶端和第一個代理之間的 HTTP 請求中沒有 Forwarded 頭域。

      第一個代理和第二個代理之間的 HTTP 請求中有 Forwarded 頭域,頭域及值為 Forwarded: for=192.0.2.43 。

      第二個代理和服務(wù)器之間的 HTTP 請求中有 Forwarded 頭域,頭域及值為 Forwarded: for=192.0.2.43, for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com”

      圖 forwarded-client-server 描述了上述情景。 圖 forwarded-client-server 由于客戶端到代理 1 的請求沒有使用代理,所以值為空或短橫線。到代理 2 時,中間經(jīng)過了代理 1,所以值為原始 IP。到服務(wù)端時,中間經(jīng)過了代理 1 和代理 2 ,所以值為原始 IP 和代理 1 IP。 上面就是關(guān)于 RFC7239 中部分內(nèi)容的解讀。看到這里,想必你已有絲絲頭緒,接下來我們再捋一捋。

      IP 代理實驗

      首先我在自己的測試服務(wù)器上安裝并啟動了 Nginx,它的默認(rèn)日志格式如下:

      1

      2

      3

      4

      log_format main

      '$remote_addr - $remote_user [$time_local] "$request" '

      '$status $body_bytes_sent "$http_referer" '

      '"$http_user_agent" "$http_x_forwarded_for"';

      即 access.log 文件中會記錄客戶端 IP 地址、客戶端時間、請求方式、響應(yīng)狀態(tài)碼、響應(yīng)正文大小、Referer、User-Agent 和代理清單。

      提示:Nginx 中 $http_x_forwarded_for 對應(yīng)的值這里稱為代理清單,它與 RFC7239 中的 Forwarded 含義相同。

      當(dāng)我使用計算機終端瀏覽器訪問測試服務(wù)器地址時,對應(yīng)的日志記錄如下:

      1

      180.137.156.168 - - [24/Nov/2019:12:41:19 +0800] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15" "-"

      服務(wù)器記錄到的信息含義如下:

      客戶端 IP 為 180.137.156.168

      客戶端時間為 [24/Nov/2019:12:41:19 +0800]

      請求方式為 GET / HTTP/1.1

      響應(yīng)狀態(tài)碼為 200

      響應(yīng)正文大小為 612

      Referer 為短橫線,即為空

      User-Agent 顯示瀏覽器品牌為 Safari

      代理清單為短橫線,即為空。

      由于本次并未使用 IP 代理,那么代理清單自然就是短橫線。接著我們用 Python 代碼測試一下,代碼片段 Python-Request 為測試代碼。

      1

      2

      3

      import requests

      resp = requests.get("http://111.231.93.117/")

      print(resp.status_code)

      代碼片段 Python-Request 代碼運行結(jié)果為 200,即目標(biāo)服務(wù)器正確響應(yīng)了本次請求。對應(yīng)的日志記錄如下:

      1

      180.137.156.168 - - [24/Nov/2019:12:49:41 +0800] "GET / HTTP/1.1" 200 612 "-" "python-requests/2.21.0" "-"

      這次也沒有使用 IP 代理,所以代理清單依舊是短橫線。現(xiàn)在用代理 IP 測試一下,代碼片段 Forwarded-Test 中使用了 IP 代理,我們就用它進行測試即可。這里的代理服務(wù)器 IP 地址為 220.185.128.170,根據(jù)之前對 RFC7239 的了解,猜測本次請求對應(yīng)的 Forwarded 記錄的會是原始 IP,而客戶端 IP 則是代理服務(wù)器的 IP。 代碼運行后,服務(wù)器記錄到對應(yīng)的日志信息如下:

      1

      220.185.128.170 - - [24/Nov/2019:12:52:58 +0800] "GET / HTTP/1.1" 200 612 "http://www.sfhfpc.com" "python-requests/2.21.0" "180.137.156.168"

      果然,記錄中客戶端 IP 對應(yīng)的是 220.185.128.170,即代理服務(wù)器的 IP。Forwarded 中記錄的 180.137.156.168 是 Python 程序所在的計算機 IP 地址,即原始 IP。 這與 RFC7239 的描述完全相符,服務(wù)端可以通過 Forwarded 找到原始 IP,甚至是使用過的代理服務(wù)器 IP。

      調(diào)皮的 IP 代理商

      剛才我們用的是普通 IP 代理,由于它很容易被識別,達(dá)不到隱匿的目的,所以 IP 代理商又推出了高匿代理。 高匿代理: 相對于普通 IP 代理而言,使用高匿代理后,原始 IP 會被隱藏得更好,服務(wù)端更難發(fā)現(xiàn)。 這里我使用了 芝麻代理 服務(wù)商提供的免費高匿 IP,注冊后就可以領(lǐng)取免費 IP,簡直就是開箱即用。 將代碼片段 Forwarded-Test 中用于設(shè)置代理服務(wù)器 IP 和端口號的字段值改為高匿 IP 及對應(yīng)的端口號即可,例如:

      1

      2

      3

      # 代理服務(wù)器

      proxyHost = "58.218.92.132" # "220.185.128.170"

      proxyPort = "2390" # "9999"

      保存更改后運行代碼,對應(yīng)的日志記錄如下:

      1

      125.82.188.4 - - [24/Nov/2019:13:05:07 +0800] "GET / HTTP/1.1" 200 612 "http://www.sfhfpc.com" "python-requests/2.21.0" "-"

      原始 IP 為 125.82.188.4,代理清單為短橫線。細(xì)心的你可能會有疑問,為什么填寫的代理 IP 是 58.218.92.132,而日志中的卻不是呢? 這是代理服務(wù)商做了多一層的轉(zhuǎn)移,58.218.92.132 是給用戶的入口,代理商的服務(wù)端會將入口為 58.218.92.132 的請求轉(zhuǎn)給地址為 125.82.188.4。其中過程我們不用深究,高匿代理和普通代理的原理會再開一篇文章進行討論。 日志記錄說明高匿 IP 能夠幫助我們實現(xiàn)隱匿的目的。說到這里不得不提一下,芝麻代理高匿 IP 的質(zhì)量真的好,聽說他們的 IP 還支持高并發(fā)調(diào)用,有需求的朋友不妨去試試。

      機智的你和想當(dāng)然的開發(fā)者

      難道普通代理就一定會被 X-Forward-For 發(fā)現(xiàn)嗎? 辦法總是會有的,翻一下 http://www.sfhfpc.com 或者公眾號韋世東學(xué)算法和反爬蟲說不定靈感就來了!在解讀 RFC7239 - Example Usage 時,我們了解到 X-Forward-For 會記錄原始 IP,在使用多層 IP 代理的情況下記錄的是上層 IP。利用這個特點,是不是可以偽造一下呢? 既然 X-Forward-For 和 Referer 一樣是頭域,那么就說明它可以被人為改變。我們只需要在請求時加上 X-Forward-For 請求頭和對應(yīng)的值即可。代碼片段 Python-Request-CustomHeader 實現(xiàn)了這樣的需求。

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      import requests

      # 請求地址

      targetUrl = "http://111.231.93.117/"

      # 代理服務(wù)器

      proxyHost = "220.185.128.170"

      proxyPort = "9999"

      proxyMeta = "http://%(host)s:%(port)s" % {

      "host": proxyHost,

      "port": proxyPort,

      }

      proxies = {

      "http": proxyMeta,

      }

      header = {

      "Referer": "http://www.sfhfpc.com",

      "X-Forwarded-For": "_",

      }

      resp = requests.get(targetUrl, proxies=proxies, headers=header)

      print(resp.status_code)

      print(resp.text)

      代碼片段 Python-Request-CustomHeader 代碼運行后,控制臺結(jié)果如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      200

      Welcome to nginx!

      Welcome to nginx!

      If you see this page, the nginx web server is successfully installed and

      working. Further configuration is required.

      For online documentation and support please refer to

      nginx.org.

      Commercial support is available at

      nginx.com.

      Thank you for using nginx.

      響應(yīng)狀態(tài)碼是 200,并且返回了 Welcome to nginx 等字樣,這說明請求成功。對應(yīng)的日志記錄為:

      1

      220.185.128.170 - - [24/Nov/2019:14:13:24 +0800] "GET / HTTP/1.1" 200 612 "http://www.sfhfpc.com" "python-requests/2.21.0" "_, 180.137.156.168"

      記錄顯示,原始 IP 為 220.185.128.170、代理清單為 “_, 180.137.156.168”。實際上原始 IP 是 180.137.156.168,而代理服務(wù)器的 IP 是 220.185.128.170。代理清單中多出來的短橫線是我們在代碼中加上的,這里居然也顯示了。這說明我們只需要在請求時附帶上 X-Forward-For 頭域就可以達(dá)到偽造的目的。 如果我想讓服務(wù)端認(rèn)為原始 IP 為 112.113.115.116,那么只需要將代碼片段 Python-Request-CustomHeader 中 header 對象中 X-Forwarded-For 鍵對應(yīng)的值設(shè)置為 112.113.115.116 即可。 保存后運行代碼,對應(yīng)的日志記錄如下:

      1

      220.185.128.170 - - [24/Nov/2019:14:28:08 +0800] "GET / HTTP/1.1" 200 612 "http://www.sfhfpc.com" "python-requests/2.21.0" "112.113.115.116, 180.137.156.168"

      根據(jù) RFC7239 - Example Usage,開發(fā)者會認(rèn)為代理清單中的第一組 IP 地址是原始 IP,殊不知這是我們特意為他準(zhǔn)備的。

      小結(jié)

      HTTP PHP Python

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:值得收藏的6個Excel函數(shù)公式
      下一篇:電子表格為什么打不開(電子表格為什么打不開了)
      相關(guān)文章
      精品亚洲aⅴ在线观看| 亚洲国产精品美女久久久久| 亚洲女子高潮不断爆白浆| 亚洲AV人无码综合在线观看| 亚洲精品无码久久一线| 国产亚洲蜜芽精品久久| 亚洲av乱码一区二区三区按摩| 亚洲一区二区三区成人网站 | 亚洲精品白色在线发布| 亚洲国产精品免费视频| 亚洲大尺度无码专区尤物| 亚洲精品无码永久在线观看你懂的| 亚洲中文字幕久久精品无码喷水 | 噜噜综合亚洲AV中文无码| 亚洲精品第一国产综合亚AV| 亚洲色一区二区三区四区| 亚洲国产精品无码久久| 欧美激情综合亚洲一二区| 香蕉视频亚洲一级| 亚洲第一福利网站在线观看| 亚洲精品无码av天堂| 亚洲最大激情中文字幕| 亚洲人成网站在线播放vr| 国产亚洲婷婷香蕉久久精品| 久久精品国产精品亚洲色婷婷| 久久青青草原亚洲AV无码麻豆| 水蜜桃亚洲一二三四在线| 亚洲精品综合久久中文字幕| 亚洲国产精品白丝在线观看| 亚洲中字慕日产2021| 亚洲精品无码av片| 亚洲av区一区二区三| 中文字幕在线亚洲精品 | 亚洲精品无码乱码成人| 亚洲AV成人无码久久精品老人 | 久久精品亚洲日本波多野结衣| 亚洲精品第一国产综合境外资源| 亚洲最大av无码网址| 亚洲香蕉成人AV网站在线观看| 国产亚洲一区二区在线观看 | 亚洲视频免费一区|