1、感謝 @shenJin 的建議,修改了本地hosts,這樣在瀏覽器地址框裏輸入的是自定義域名,省得每次截圖都要打碼。
不過這個8000埠還是很彆扭,想要直接訪問80埠,該怎麼做呢?
考慮反向代理。首先安裝Nginx,然後改配置。
參考這裡Ubuntu16.04.1 安裝Nginx順利的安裝了Nginx,用IP訪問可以顯示歡迎界面,如下:
不過由於阿里雲要求域名得註冊備案,所以反代到http://www.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/") 客戶端列印:帶斜槓和不帶
# 我來改成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、我們看到的是代理修改之後的HTTP請求,http.server庫產生的原始GET請求有帶斜槓,請求內容不包含服務主機的IP。這符合一般情況,無論什麼操作系統:
1)按TCP/IP協議,對端的IP地址應該封裝在IP頭部,而不該出現在HTTP頭部。
2)做個試驗,Windows環境下隨便訪問下面這個URL,用chrome檢查發送的http請求:
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網站。比如:
我想模擬這個過程。比如這樣:我本地向自己的伺服器發送一個請求,讓我的伺服器取訪問http://www.baidu.com,以實現宣傳百度的作用。
不過目前為止沒有成功,發現GET請求的Host欄位很關鍵。
如果Host不以/結尾,那麼GET後面的就被認為是本地文件夾路徑;只有Host以/結尾,GET後面的才會被當做鏈接請求,但這時也報2個錯誤。
以後再更。
推薦閱讀: