1、感謝 @shenJin 的建議,修改了本地hosts,這樣在瀏覽器地址框裏輸入的是自定義域名,省得每次截圖都要打碼。

不過這個8000埠還是很彆扭,想要直接訪問80埠,該怎麼做呢?

考慮反向代理。首先安裝Nginx,然後改配置。

參考這裡Ubuntu16.04.1 安裝Nginx順利的安裝了Nginx,用IP訪問可以顯示歡迎界面,如下:

不過由於阿里雲要求域名得註冊備案,所以反代到grace.com沒配成功配置。最多在本地改hosts。

不過,本地hosts有時也會失效,就是說訪問hosts裡面配置的域名沒有解析成自己的IP,而是跳到了真實的網站。

但真實用IP+PORT時刻都是正常的。

這個原因不太清楚,暫時不折騰。可能是代理?

代理為什麼會使hosts失效? - yu_1988_happy的日誌 - 網易博客

2、今天在80埠啟動服務,突然收到一堆莫名其妙的請求。所謂莫名其妙,就是GET請求的路徑並不是我網站的路徑,而是某些非法網站的URL,據說這個算是非法網站自我宣傳的手段。

另外@shellpaul 注意到一個細節——正常請求是從當前根目錄往下,所以GET之後一般是 /,但是今天收到奇怪的請求……是不帶/的。

正常請求
奇怪的請求

讓我們來複現這個現象:首先python2,然後python3。

(中途一個小插曲:用anaconda裝python2.7虛擬環境,結果發現什麼虛擬創建都創不了,不知道什麼時候壞了,重裝anaconda3解決)

為了接觸到HTTP的原始請求,python2藉助httplib,python3藉助http.cllient。常用的requests其實對這個庫的封裝。

"""Python2 @shellpaul """
import requests
import httplib

def patch_send():
old_send= httplib.HTTPConnection.send
def new_send(self, data):
print(data)
data = data.replace("GET /", "GET ")
print(data)
return old_send(self, data)
httplib.HTTPConnection.send= new_send

patch_send()
requests.get("http://127.0.0.1:80/http://www.baidu.com/")

客戶端列印:帶斜槓和不帶

服務端列印:可以看到GET請求帶不帶斜槓算,對服務端是等效的,注意第二個轉義

# 我來改成Python3:

"""Python3"""
import requests
import http.client

def patch_send():
old_send= http.client.HTTPConnection.send
def new_send(self, data):
data = data.decode("utf8").replace("GET /", "GET ").encode("utf8")
print(data.decode("utf8"))
return old_send(self, data)
http.client.HTTPConnection.send= new_send

patch_send()
requests.get("http://127.0.0.1:80/http://www.baidu.com/")

服務端:也可以模擬出來

本來事情到此就該結束了,不過以上成功的復現都是客戶端服務端都在本地,客戶端訪問127.0.0.1。

但是昨天我在遠程的windows10上用Python3起一個客戶端,GET請求原始就是不帶斜槓。不知道鍋在操作系統|遠程本地|還是代理,於是同樣的代理換win7再試一次……

找到了,鍋在客戶端的代理!

我們把代碼裏replace那一句去掉,意思是直接用它產生的請求不做任何修改,然後來試驗

打開代理:

客戶端請求:1、不帶斜槓 2、GET裡麪包含IP
服務端收到:不帶斜槓?

不開代理:

客戶端請求:1、帶斜槓 2、GET裡面不包含IP

我的理解:

1、我們看到的是代理修改之後的HTTP請求,http.server庫產生的原始GET請求有帶斜槓,請求內容不包含服務主機的IP。這符合一般情況,無論什麼操作系統:

1)按TCP/IP協議,對端的IP地址應該封裝在IP頭部,而不該出現在HTTP頭部。

2)做個試驗,Windows環境下隨便訪問下面這個URL,用chrome檢查發送的http請求:

linux上anaconda的卸載 - CSDN博客?

blog.csdn.net

請求帶斜槓沒錯吧~

2、伺服器這樣「收到」的請求: 帶斜槓表示從根目錄開始的絕對路徑,不帶表示從當前目錄網線相對路徑。

由於服務本身就是在根目錄啟動,所以對服務端,無論收到GET aa還是GET /AA,上一句Not Found查找的目錄都是/aa,此時的相對絕對表示的是同一個目錄。

回頭來看最開始的一堆非法請求,到底是怎麼一回事呢?

發過來的請求應該是類似這樣:

GET http://www.baidu.com/ HTTP/1.1
Host: xx.xx.xx.xx

對方為什麼故意去掉了GET /的斜槓 ?

我的服務端是Django,它對GET aa/bb的理解是拿到本地當前路徑下的aa目錄下的bb文件,這和GET/ aa/bb沒什麼區別;但滿足一定條件時也可能會有不同理解,可能把GET aa/bb理解為從aa網站獲取bb文件,也就是我會再發送一次請求,由此訪問到aa網站。比如:

這個時候就會去訪問47開頭的網站……而不是當成一個本地目錄

我想模擬這個過程。比如這樣:我本地向自己的伺服器發送一個請求,讓我的伺服器取訪問baidu.com,以實現宣傳百度的作用。

不過目前為止沒有成功,發現GET請求的Host欄位很關鍵。

如果Host不以/結尾,那麼GET後面的就被認為是本地文件夾路徑;只有Host以/結尾,GET後面的才會被當做鏈接請求,但這時也報2個錯誤。

以後再更。

推薦閱讀:

相關文章