Xây dựng 1 proxy với Go và net/http
July 15, 2019
Golang
proxy
net/http
Khái niệm proxy thì chắc hẳn ai cũng biết tuy nhiên mình vẫn muốn nhắc lại. Proxies là các hành động nằm trung gian ở giữa client và server. Chúng có thể can thiệp các tiến trình hoặc gì đơn giản là forward các request.
Có rất nhiều phương thức proxies như
Tuy nhiên phổ biến nhất thì vẫn là http proxies vì đa số người dùng bình thường sử dụng http request.
Diagram
Http_proxy=https://your-ip:1234
+--------------+ +----------------+ +----------------+
| | | | | |
| client +----------^+ forward proxy +--------^+ Server |
| | | | | |
+--------------+ +----------------+ +----^-----------+
|
|
+---------------+ |
| | |
| client +-------------------------------------------+
| |
+---------------+
Không sử dụng proxy
Nhìn vào sơ đồ trên thì có thể thấy forward proxy sẽ là lớp trung gian để forward các request tới server. Lợi ích nó mang lại là gì thì mọi người đều có thể thấy rõ. Ví dụ đơn giản nhất nếu request từ client tới server không có gì nằm giữa thì bạn sẽ ko thể controll được các request. Giả xử rằng Server A ko thích bạn và họ block ip client của bạn. Vậy làm thế nào bạn có thể truy cập. đó là truy cập qua 1 proxy, proxy bạn có thể đặt ở 1 server khác. Khi bạn connect tới Server A và sử dụng forward proxy nó sẽ chuyển hướng các request của bạn tới server A và nặc danh IP là từ server forward proxy.
Tạo forward Proxy với Go
Để khởi tạo 1 proxy forward bạn cần tìm hiểu tài liệu về package http trong go import "net/http"
https://golang.org/pkg/net/http/.
type Proxy struct {
}
func NewProxy() *Proxy { return &Proxy{} }
Trước tiên khởi 1 struct và 1 method NewProxy, method này sẽ có nhiệm vụ khởi tạo đối tượng Proxy.
Để lắng nghe được các request từ client bạn cần phải mở 1 port và sử dụng method ListenAndServe
từ package http
.
func main() {
proxy := NewProxy()
err := http.ListenAndServe(":1234", proxy)
}
vậy là OK rồi bây giờ cần phải xử lý proxy với methods ServeHTTP các bạn có thể viết như sau
func (p *Proxy) ServeHTTP(wr http.ResponseWriter, r *http.Request) {
var resp *http.Response
var err error
var req *http.Request
client := &http.Client{}
req, err = http.NewRequest(r.Method, r.RequestURI, r.Body)
for name, value := range r.Header {
req.Header.Set(name, value[0])
}
resp, err = client.Do(req)
r.Body.Close()
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
return
}
for k, v := range resp.Header {
wr.Header().Set(k, v[0])
}
wr.WriteHeader(resp.StatusCode)
io.Copy(wr, resp.Body)
resp.Body.Close()
}
Vậy là xong bạn có thể sử dụng luôn với proxy này.
nếu bạn sử dụng curl để test thử thì có thể chạy với command như sau
curl -x 127.0.0.1:1234 http://example.com
Nếu bạn sử dụng trình duyệt thì có thể tham khảo hướng dẫn thay đổi proxy của trình duyệt thì có thể tham khảo 1 vài hướng dẫn https://customers.trustedproxies.com/knowledgebase.php?action=displayarticle&id=10
Một lưu ý nhỏ bài viết này chỉ hướng dẫn bạn khởi tạo 1 proxy đơn giản và chỉ có thể truy cập được các trang web mà không sử dụng SSL. Tuy nhiên bài viết sau mình sẽ hướng dẫn làm 1 web proxy hoàn chỉnh hơn và có thể truy cập tất các các trang với SSL.
Hi vọng bài viết có thể mang lại 1 chút kiến thức cho các bạn.