golang实现简单的TCP代理

TCP Proxy

go 复制代码
package main

import (
	"io"
	"log"
	"net"
	"sync"
)

// go实现简单的TCP代理

// TCPProxy 是一个 TCP 代理
type TCPProxy struct {
	listenAddr string
	targetAddr string
}

// NewTCPProxy 创建一个新的 TCP 代理
func NewTCPProxy(listenAddr, targetAddr string) *TCPProxy {
	return &TCPProxy{
		listenAddr: listenAddr,
		targetAddr: targetAddr,
	}
}

// Serve 开始监听并代理 TCP 连接
func (p *TCPProxy) Serve() error {
	// 监听 TCP 连接
	listener, err := net.Listen("tcp", p.listenAddr)
	if err != nil {
		return err
	}
	defer listener.Close()
	log.Printf("tcp proxy listening at: %s\n", listener.Addr())
	// 处理 TCP 连接
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("listener accept error: %s\n", err)
			continue
		}
		go p.handleConnection(conn)
	}
}

// handleConnection 处理 TCP 连接
func (p *TCPProxy) handleConnection(conn net.Conn) {
	defer conn.Close() // 关闭代理连接
	log.Printf("accepted new connection %s\n", conn.RemoteAddr())
	// 创建目标连接
	targetConn, err := net.Dial("tcp", p.targetAddr)
	if err != nil {
		log.Printf("dial target addr: %s error: %s\n", p.targetAddr, err)
		return
	}
	defer targetConn.Close() // 关闭目标连接
	log.Printf("tcp proxy client addr: %s\n", targetConn.LocalAddr())
	// 处理 TCP 流 ,在客户端和目标服务器之间双向转发数据
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		n, err := io.Copy(conn, targetConn)
		if err != nil {
			log.Printf("copy bytes from %s to %s error: %s", conn.RemoteAddr(), targetConn.RemoteAddr(), err)
			return
		}
		log.Printf("copied %d bytes from %s to %s", n, conn.RemoteAddr(), targetConn.RemoteAddr())

	}()
	go func() {
		defer wg.Done()
		n, err := io.Copy(targetConn, conn)
		if err != nil {
			log.Printf("copy bytes from %s to %s error: %s", targetConn.RemoteAddr(), conn.RemoteAddr(), err)
			return
		}
		log.Printf("copied %d bytes from %s to %s", n, targetConn.RemoteAddr(), conn.RemoteAddr())
	}()
	// 等待两个复制操作完成
	wg.Wait()
}

func main() {
	proxy := NewTCPProxy("127.0.0.1:8080", "127.0.0.1:8081")
	if err := proxy.Serve(); err != nil {
		log.Fatal(err)
	}
}

Server

go 复制代码
package main

import (
	"bufio"
	"log"
	"net"
)

// TCP Server端测试
// handle 处理函数
func handle(conn net.Conn) {
	defer conn.Close() // 关闭连接
	reader := bufio.NewReader(conn)
	for {
		var buf [512]byte
		n, err := reader.Read(buf[:]) // 读取数据
		if err != nil {
			log.Printf("read from client err: %s\n", err)
			break
		}
		log.Printf("read %d bytes from client\n", n)
		recvStr := string(buf[:n])
		log.Printf("received data from client: %s\n", recvStr)
		n, err = conn.Write([]byte(recvStr)) // 发送数据
		if err != nil {
			log.Printf("write data to client err: %s\n", err)
			return
		}
		log.Printf("write %d bytes to client\n", n)
	}
}

func main() {
	listener, err := net.Listen("tcp", "127.0.0.1:8081")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("server listening at: %s\n", listener.Addr())
	for {
		conn, err := listener.Accept() // 监听客户端的连接请求
		if err != nil {
			log.Printf("listener accept error: %s\n", err)
			continue
		}
		go handle(conn) // 启动一个goroutine来处理客户端的连接请求
	}
}

Client

go 复制代码
package main

import (
	"bufio"
	"log"
	"net"
	"os"
	"strings"
)

// TCP 客户端
func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("client addr: %s\n", conn.LocalAddr())
	defer conn.Close() // 关闭TCP连接
	inputReader := bufio.NewReader(os.Stdin)
	for {
		input, _ := inputReader.ReadString('\n') // 读取用户输入
		inputInfo := strings.Trim(input, "\r\n")
		if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
			return
		}
		n, err := conn.Write([]byte(inputInfo)) // 发送数据
		if err != nil {
			log.Printf("write data to server err: %s\n", err)
			return
		}
		log.Printf("write %d bytes to server\n", n)
		buf := [512]byte{}
		n, err = conn.Read(buf[:])
		if err != nil {
			log.Printf("read data from server err: %s\n", err)
			return
		}
		log.Printf("read %d bytes from server\n", n)
		log.Printf("received data from server: %s\n", string(buf[:n]))
	}
}
相关推荐
Hacker_Nightrain40 分钟前
网络安全CTF比赛规则
网络·安全·web安全
网络安全指导员1 小时前
恶意PDF文档分析记录
网络·安全·web安全·pdf
co0t2 小时前
计算机网络(11)和流量控制补充
服务器·网络·计算机网络
白总Server2 小时前
JVM解说
网络·jvm·物联网·安全·web安全·架构·数据库架构
清尘沐歌3 小时前
有什么好用的 WebSocket 调试工具吗?
网络·websocket·网络协议
Li_0304063 小时前
Java第十四天(实训学习整理资料(十三)Java网络编程)
java·网络·笔记·学习·计算机网络
Tony聊跨境3 小时前
什么是 ISP:了解互联网服务提供商的作用
网络·人工智能·isp
earthzhang20213 小时前
《深入浅出HTTPS》读书笔记(7):安全的密码学Hash算法
网络·网络协议·http·https·1024程序员节
Hacker_Oldv3 小时前
【网络工程】计算机硬件概述
前端·网络·安全·web安全
甘橘籽4 小时前
【RPC】 gRPC、pb基本使用--经验与总结
golang