2.4.4 代理一个TCP客户端
go
不能直接访问的目标网站:
package main
import (
"io"
"log"
"net"
)
// echo is a handler function that simply echoes received data.
func echo(conn net.Conn) {
defer conn.Close()
// Create a buffer to store received data.
b := make([]byte, 512)
//代理连接上目标网站
if _, err := conn.Write([]byte("proxy success connect website")); err != nil {
log.Fatalln("Unable to write data")
}
for {
// Receive data via conn.Read into a buffer.
size, err := conn.Read(b[0:])
if err != nil && err != io.EOF {
log.Println("Unexpected error")
break
}
if err == io.EOF && size == 0 {
log.Println("Client disconnected")
break
}
log.Printf("Received %d bytes: %s", size, string(b))
// Send data via conn.Write.
log.Println("Writing data")
if _, err := conn.Write(b[0:size]); err != nil {
log.Fatalln("Unable to write data")
}
}
}
func main() {
// Bind to TCP port 20080 on all interfaces.
listener, err := net.Listen("tcp", ":20000")
if err != nil {
log.Fatalln("Unable to bind to port")
}
log.Println("Listening on 0.0.0.0:20080")
for {
// Wait for connection. Create net.Conn on connection established.
//等待连接
conn, err := listener.Accept()
log.Println("Received connection")
if err != nil {
log.Fatalln("Unable to accept connection")
}
// Handle the connection. Using goroutine for concurrency.
//处理连接
go echo(conn)
}
}
go
代理:
package main
import (
"io"
"log"
"net"
)
func handle(src net.Conn) {
//website:127.0.0.1:80
dst, err := net.Dial("tcp", "127.0.0.1:20000")
if err != nil {
log.Fatalln("Unable to connect to our unreachable host")
}
defer dst.Close()
//告诉joe你已经通过代理连上了目标网站
if _, err := src.Write([]byte("Success connect proxy")); err != nil {
log.Fatalln("Unable to write data")
}
go func() {
//把客户端流量导到目标网站
if _, err := io.Copy(dst, src); err != nil {
log.Fatalln(err)
}
}()
//防止IO流阻塞
if _, err := io.Copy(src, dst); err != nil {
log.Fatalln(err)
}
}
func main() {
listener, err := net.Listen("tcp", ":30000")
if err != nil {
log.Fatalln("Unable to bind port")
}
for {
conn, err := listener.Accept()
if err != nil {
log.Fatalln("Unable to accept connection")
}
go handle(conn)
}
}
go
客户端:
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
)
func main() {
// Connect to the server on TCP port 20080.
conn, err := net.Dial("tcp", "127.0.0.1:30000")
if err != nil {
log.Fatalln("Unable to connect to the server")
}
defer conn.Close()
// Create a scanner to read input from the user.
scanner := bufio.NewScanner(os.Stdin)
// Create a goroutine to read and display server responses.
go func() {
for {
// Read server response.
response := make([]byte, 512)
size, err := conn.Read(response)
if err != nil {
log.Fatalln("Error reading from server:", err)
return
}
fmt.Printf("imformation: %s\n", string(response[:size]))
}
}()
// Read user input and send it to the server.
for {
fmt.Print("Enter text to send to the server: \n")
scanner.Scan()
text := scanner.Text()
// Send user input to the server.
_, err := conn.Write([]byte(text))
if err != nil {
log.Fatalln("Error writing to server:", err)
return
}
}
}
效果:
客户端能够收到来自代理的信息和目标网站的信息
输入aaaaa能够收到来自目标网站的回显效果,说明示例基本上完成了流量转发的功能,这里只是一个简单的示例,大家可以在这个基础上进行扩充。