正向代理隱藏了真實客戶端向服務器發送請求,反向代理隱藏了真實服務器向客戶端提供服務。
正向代理:
小王要結婚了,可是手上拿不出彩禮錢,他就找了好兄弟小張,小張同樣沒錢,但是小張認識思聰,於是小張從王思聰那裏借到了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.Listener
backendAddress 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))
}
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,轉發服務器端口9999
go p.Run()
for _, c := range client.NewClient(":9000", 3) { //客戶端向9000代理端口發送請求
go c.Run()
}
select {}
獲取完整代碼見Github地址:https://github.com/slpslpslp/proxyDemo
想學習更多Go知識,請關注公衆號:Golang技術分享。