3min快速掌握Go语言正/反向代理的姿势

3min,快速,掌握,go,语言,反向,代理,姿势 · 浏览次数 : 618

小编点评

**反向代理** **正向代理** 正向代理在客户端进行请求时,代理程序将代理出站请求,客户端无法感知代理逻辑。反向代理在服务端进行请求时,代理程序将代理入站请求,服务端无法感知代理逻辑。 **正向代理实践** * VPN/梯子 * 反向代理 **反向代理实践** 反向代理用于将入站请求转发到服务器。这种代理模式中,服务端对代理程序的感知能力非常有限,甚至可能无法识别代理程序的存在。 **反向代理的优点** * 降低响应时间 * 提高安全性 **反向代理的缺点** * 隐藏代理逻辑 * 无法提供客户端级功能,例如缓存和错误处理

正文

先重温一下什么叫反向代理,正向代理。

鹅厂二面,nginx回忆录

所谓正向/反向代理取决于代理的是出站请求,还是入站请求

正向代理: 代理的出站请求, 客户端能感知到代理程序,架构上距离客户端更近。
反向代理: 代理的是入站请求,客户端认为代理程序就是服务器,客户端感知不到代理逻辑,架构上距离服务端更近。


正向代理的实践

正向代理的一个日常实践就是vpn/梯子。

这几天刚好遇到了一个正向代理的case, 简单记录一下。

name.com集群无法访问外界的机器, 于是在机房部署边缘代理,代理出站请求。

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
)

func ProxyHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Printf("receive a request from {0}  {1}: \n", r.RemoteAddr, r.RequestURI)
	if r.Host != "localhost:8080" {
		director := func(req *http.Request) {
			req.URL.Scheme = "http"
			req.URL.Host = r.Host
			req.Host = r.Host
		}
		proxy := &httputil.ReverseProxy{Director: director}
		proxy.ServeHTTP(w, r)
	} else {
		http.NotFound(w, r)
	}
}

func main() {
	if err := http.ListenAndServe(":8080", http.HandlerFunc(ProxyHandler)); err != nil {
		log.Fatal(err)
	}
}

其中要注意的就是,正向代理式要规避死循环代理。

该代理程序靠近clients,client对于外部ip的请求,先发到代理程序。

//针对httpclient设置proxy
	transport := &http.Transport{
		Proxy: http.ProxyURL(proxyURL),
	}

	//adding the Transport object to the http Client
	client := &http.Client{
		Transport: transport,
	}

下面使用curl指令演示(-x 后接代理地址)
curl -x 127.0.0.1:8080 www.baidu.com


反向代理的实践

反向代理, 服务入站请求。
前几天利用golang实现了反向代理程序,引出了[Host请求头在反代中的关键作用]{https://www.cnblogs.com/JulianHuang/p/16639016.html}:

host 请求头用于在 (单负载主机支撑多域名)中区分服务域名,对应到 nginx --http context--- server context -- server_name 配置节。

对于proxy.com的请求,都被透明无感代理到A.com

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
)

func ReverseProxyHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Printf("receive a request from %s,request header: %s: \n", r.RemoteAddr, r.Header)

	target := "www.baidu.com"
	director := func(req *http.Request) {
		req.URL.Scheme = "https"
		req.URL.Host = target
		req.Host = target
	}
	proxy := &httputil.ReverseProxy{Director: director}
	proxy.ServeHTTP(w, r)
        fmt.Printf("receive the destination website response header: %s\n", w.Header())
}

func main() {
	fmt.Printf("Starting server at port 8080\n")
	if err := http.ListenAndServe(":8080", http.HandlerFunc(ReverseProxyHandler)); err != nil {
		log.Fatal(err)
	}
}

以上代理服务器proxy.com部署在服务侧www.baidu.com;
proxy.com接收clients的入站请求,反向转发到www.baidu.com。

curl www.proxy.com返回baidu.com的内容。

GO快闪#

本文总结了go语言正/反向代理的姿势。

与3min快速掌握Go语言正/反向代理的姿势相似的内容: