正反向代理Golang实现

正向代理隐藏了真实客户端向服务器发送请求,反向代理隐藏了真实服务器向客户端提供服务。

Explanation

正向代理:

小王要结婚了,可是手上拿不出彩礼钱,他就找了好兄弟小张,小张同样没钱,但是小张认识思聪,于是小张从王思聪那里借到了20万交到了小王手上。对于思聪来说,他并不知道真正借钱的人是小王。

常见例子:科学上网VPN

反向代理:

小王结婚买房,他找到贷款中介,贷款中介给了他50万。但中介找哪个资方出资50万,小王完全不知情。

常见例子:Nginx反向代理服务器

代理架构图如下所示

Golang示例代码

server.go

type Server struct {listener net.Listener}func NewServer(address ...string) []*Server {s := make([]*Server, 0)for _, a := range address {lst, _ := net.Listen("tcp", a)s = append(s, &Server{listener: lst,})}return s}func (s *Server) Run() {for {    conn, _ := s.listener.Accept() //服务器监听代理请求go s.handler(conn)}}func (s *Server) handler(conn net.Conn) {for {msg := make([]byte, 1024)_, _ = conn.Read(msg) //读取代理转发的客户端请求fmt.Println(string(msg))    _, _ = conn.Write([]byte(fmt.Sprintf("message from Server: %s", s.listener.Addr().String()))) //服务器写入内容}}

agent.go

type Proxy struct {listener net.ListenerbackendAddress string}func NewProxy(agentAddress, serverAddress string) *Proxy {lst, _ := net.Listen("tcp", agentAddress)return &Proxy{listener: lst,backendAddress: serverAddress,}}func (p *Proxy) Run() {for {    frontConn, _ := p.listener.Accept() //等待客户端请求backendConn, _ := net.Dial("tcp", p.backendAddress)go p.Agent(frontConn, backendConn)}}func (p *Proxy) Agent(frontConn, backendConn net.Conn) { //转发客户端请求与服务器返回go io.Copy(backendConn, frontConn)go io.Copy(frontConn, backendConn)}

client.go

type Client struct {conn net.Conn}func NewClient(proxyAddress string, num int) []*Client {c := make([]*Client, 0)for i := 0; i < num; i++ {conn, _ := net.Dial("tcp", proxyAddress)c = append(c, &Client{conn: conn})}return c}func (c *Client) Run() {  //发起客户端请求_, _ = c.conn.Write([]byte(fmt.Sprintf("message from client: %s", c.conn.LocalAddr().String())))msg := make([]byte, 1024)  //读取代理返回内容c.conn.Read(msg)fmt.Println(string(msg))}

main.go

func main() {  servers := server.NewServer(":9998", ":9999") //开启本地9998和9999为服务器端口for _, s := range servers {go s.Run()}  p := proxy.NewProxy(":9000", ":9999") //代理服务器端口9000,转发服务器端口9999go p.Run()  for _, c := range client.NewClient(":9000", 3) { //客户端向9000代理端口发送请求go c.Run()}select {}

获取完整代码见Github地址:

推荐阅读

首发特性:goproxy.cn 现已推出首个 Go 模块代理统计数据 API

喜欢本文的朋友,欢迎关注“Go语言中文网”:

Go语言中文网启用微信学习交流群,欢迎加:,投稿亦欢迎