gorawsock

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 8, 2024 License: MIT Imports: 17 Imported by: 0

README

gorawsock

这个库主要是通过gopacket库模拟了tcp/udp通讯,实现数据传输的功能,examples 目录下 client.goserver.go 就是两个测试程序 。测试这两个程序,是通过python socket模拟服务器和客户端测试的,两个程序都能正常使用。

测试的 client.py 代码如下:

import socket
import time

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('192.168.1.3', 8000))

client.send(bytes('i am " + client.getsocketname()[0] + 'hello 192.168.1.3','utf-8'))
from_server = client.recv(4096)
print(str(from_server))
time.sleep(5)
client.close()

运行截图如下:

image

附加说明

在一些情况下,服务器端可能尝试端口复用,比如说,原有主机有某些程序运行在80端口,你可以在主机上运行此rawsock 构造的服务程序,也开启80端口,两个程序启动并不冲突,都可以监听80端口,但正常情况客户端不是 rawsock 实现的程序 尝试连接服务器的80端口,是不能正常与 rawsock 服务器通讯的,因为首先会连接到原有程序的80端口,那么这个时候,就可以 通过使用 rawsock 实现客户端,构造异形的 tcp连接系统,与服务器通讯,注意:服务器端也必须是和客户端同样的规则,比如说, seq与ack的确认方式改变,这样客户端既不与原有程序连接,又能和 rawsock 构造的服务器保持稳定通讯。

以上只是思路,目前没有测试实现,后续有时间会上测试代码。

关于代码中的说明

在客户端连接服务器时有函数:

Connect(targetIP net.IP, targetPort uint16, nexthopMAC net.HardwareAddr) (*Socket, error)

其中有参数 nexthopMAC 这个指定的是下一跳物理地址, 在tcp封包中, 网络接口层 eth 需要传递下一跳的物理地址, 在规则中,同一个局域网属于直连,那么下一跳地址就是目标机器的MAC地址,如果是不在同一个局域网,那么这个就是网关的物理地址。 注意: 我们这里排除掉回环的情况(127.0.0.1本地通讯)

Documentation

Index

Constants

View Source
const (
	IFObtainType_IP = iota
	IFObtainType_DeviceLnkName
)
View Source
const (
	PCAP_IF_LOOPBACK                         = 0x00000001 /* interface is loopback */
	PCAP_IF_UP                               = 0x00000002 /* interface is up */
	PCAP_IF_RUNNING                          = 0x00000004 /* interface is running */
	PCAP_IF_WIRELESS                         = 0x00000008 /* interface is wireless (*NOT* necessarily Wi-Fi!) */
	PCAP_IF_CONNECTION_STATUS                = 0x00000030 /* connection status: */
	PCAP_IF_CONNECTION_STATUS_UNKNOWN        = 0x00000000 /* unknown */
	PCAP_IF_CONNECTION_STATUS_CONNECTED      = 0x00000010 /* connected */
	PCAP_IF_CONNECTION_STATUS_DISCONNECTED   = 0x00000020 /* disconnected */
	PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE = 0x00000030 /* not applicable */
)
View Source
const (
	SocketType_STREAM int = iota + 1
	SocketType_DGRAM
)

协议类型

View Source
const (
	TCP_SIGNAL_FIN = 0x01
	TCP_SIGNAL_SYN = 0x02
	TCP_SIGNAL_RST = 0x04
	TCP_SIGNAL_PSH = 0x08
	TCP_SIGNAL_ACK = 0x10
	TCP_SIGNAL_URG = 0x20
)

TCP首部标记

View Source
const (
	TS_UNKNOWN      int = iota
	TCP_ESTABLISHED     // 连接建立:数据传送在进行
	TCP_SYN_SENT        // 已发送SYN:等待ACK
	TCP_SYN_RECV        // 已发送SYN+ACK: 等待ACK
	TCP_FIN_WAIT1       // 第一个FIN 已发送:等待ACK
	TCP_FIN_WAIT2       // 对第一个FIN 的ACK已收到:等待第二个FIN
	TCP_TIME_WAIT       // 收到第二个FIN, 已发送ACK: 等待2MSL超时
	TCP_CLOSE           // 没有连接
	TCP_CLOSE_WAIT      // 收到第一个FIN , 已发送ACK:等待应用程序关闭
	TCP_LAST_ACK        // 收到第二个FIN, 已发送ACK: 等待2MSL超时
	TCP_LISTEN          // 收到了被动打开:等待 SYN
	TCP_CLOSING         /* Now a valid state */ // 双发都已经决定同时关闭

	TCP_MAX_STATES /* Leave at the end! */
)

tcp状态

View Source
const (
	SocketMsg_Unknow int = iota
	SocketMsg_RecvData
	SocketMsg_Closed
)

socket 消息 主要用于控制接受数据使用

View Source
const PRIME_32K int = 32261

生成随机端口 来自nmap 的源码

#define PRIME_32K 32261 //Change base_port to a new number in a safe port range that is unlikely to // conflict with nearby past or future invocations of ultra_scan. static u16 increment_base_port() { static u16 g_base_port = 33000 + get_random_uint() % PRIME_32K;

	g_base_port = 33000 + (g_base_port - 33000 + 256) % PRIME_32K;
	return g_base_port;
}

Variables

View Source
var MSL int = 30

最大报文段寿命

View Source
var TCPStatusInfoMap = map[int]string{
	TCP_ESTABLISHED: "Estableshed",
	TCP_SYN_SENT:    "SynSent",
	TCP_SYN_RECV:    "SynRecv",
	TCP_FIN_WAIT1:   "FinWait1",
	TCP_FIN_WAIT2:   "FinWait2",
	TCP_TIME_WAIT:   "TimeWait",
	TCP_CLOSE:       "Close",
	TCP_CLOSE_WAIT:  "CloseWait",
	TCP_LAST_ACK:    "LastACK",
	TCP_LISTEN:      "Listening",
	TCP_CLOSING:     "Closing",
}

tcp 状态字符串

Functions

func GeneratePort

func GeneratePort() int

func GenerateTCPPackage

func GenerateTCPPackage(srcIP net.IP,
	srcMac net.HardwareAddr,
	dstIP net.IP,
	dstMac net.HardwareAddr,
	srcPort uint16,
	dstPort uint16,
	tcp_signal int,
	seq uint32,
	ack uint32,
	options []layers.TCPOption,
	payload []byte,
	isLoopback bool) ([]byte, error)

func GenerateUDPPackage

func GenerateUDPPackage(srcIP net.IP,
	srcMac net.HardwareAddr,
	dstIP net.IP,
	dstMac net.HardwareAddr,
	srcPort uint16,
	dstPort uint16,
	payload []byte,
	isLoopback bool) ([]byte, error)

func TimerCall

func TimerCall(interval int, count int, callback func())

Types

type AdapterInfo

type AdapterInfo struct {
	Flag       uint32 // 接口类型
	MTU        int    // 最大传输单元
	IsLoopback bool
	DevName    string
	MAC        net.HardwareAddr
	Addrs      []device.IPAddress
}

type ProtocolObject

type ProtocolObject struct {
	SocketType int // 数据类型
	DevHandle  *device.DeviceHandle
	Ifs        []pcap.Interface // 所有的接口信息
	AdapterInfo

	Wg sync.WaitGroup

	TCPSocketsList map[string]*Socket // 保存所有的连接的socket
	UDPSocketsList map[string]*Socket
	// contains filtered or unexported fields
}

func NewProtocolObject

func NewProtocolObject(socketType int) *ProtocolObject

func (*ProtocolObject) Accept

func (p *ProtocolObject) Accept() (*Socket, int)

func (*ProtocolObject) Append

func (p *ProtocolObject) Append(s *Socket)

func (*ProtocolObject) Bind

func (p *ProtocolObject) Bind(s *Socket)

func (*ProtocolObject) Close

func (p *ProtocolObject) Close(s *Socket) int

func (*ProtocolObject) CloseAllofSockets

func (p *ProtocolObject) CloseAllofSockets()

func (*ProtocolObject) CloseDevice

func (p *ProtocolObject) CloseDevice()

func (*ProtocolObject) Connect

func (p *ProtocolObject) Connect(targetIP net.IP, targetPort uint16, nexthopMAC net.HardwareAddr) (*Socket, error)

func (*ProtocolObject) InitAdapter

func (p *ProtocolObject) InitAdapter(iftype int, param string) error

参数说明 iftype 获取接口的方式 IFObtainType_IP 指定接口目前的IP, IFObtainType_DevlnkName 指定接口的lnk名称(windows下为符号连接) param 就是根据不同类型传递的不同数据 pcap打开设备需要执行一个设备连接符号,这么做的目的是方便传递 没有直接指定MAC地址的原因是,不能直接获取到MAC地址

func (*ProtocolObject) IsInBufferSockets

func (p *ProtocolObject) IsInBufferSockets(s *Socket) (*Socket, bool)

func (*ProtocolObject) Recv

func (p *ProtocolObject) Recv(s *Socket, result *[]byte) int

func (*ProtocolObject) RecvFrom

func (p *ProtocolObject) RecvFrom(result *[]byte) int

func (*ProtocolObject) RemoveSockFromList

func (p *ProtocolObject) RemoveSockFromList(s *Socket)

func (*ProtocolObject) Send

func (p *ProtocolObject) Send(s *Socket, payload []byte) int

func (*ProtocolObject) Sendto

func (p *ProtocolObject) Sendto(targetIP net.IP, targetPort uint16, nexthopMAC net.HardwareAddr, payload []byte) int

func (*ProtocolObject) SetTimeout

func (p *ProtocolObject) SetTimeout(timeout time.Duration)

connect and send

func (*ProtocolObject) Startup

func (p *ProtocolObject) Startup() error

func (*ProtocolObject) Wait

func (p *ProtocolObject) Wait()

type Socket

type Socket struct {
	Lock       sync.RWMutex
	Family     layers.ProtocolFamily
	SocketType int // 数据类型
	Handle     *device.DeviceHandle

	RemoteIP   net.IP // 连接来源的IP
	RemotePort uint16 // 远程端口号
	Nexthop    net.HardwareAddr

	LocalIP   net.IP
	LocalPort uint16
	LocalMAC  net.HardwareAddr

	TCPSock
	UDPSock             // 保留
	PreLenOfSent uint32 // 上一个发送的数据包长度

	LenOfRecved   uint32 // 接收的数据包长度
	RecvedPayload []byte

	// 通知回调,触发通知
	IsTriggerNotify atomic.Bool
	NotifyCallback  func()

	DataBuf *utils.Buffer
	// contains filtered or unexported fields
}

func CreateSocket

func CreateSocket(socketType int,
	localPort uint16) *Socket

func NewSocket

func NewSocket() *Socket

func (*Socket) Clone

func (p *Socket) Clone() *Socket

func (*Socket) GetLastError

func (p *Socket) GetLastError() error

获取最近的错误

func (*Socket) GetNextSeq

func (p *Socket) GetNextSeq() uint32

获取下一个包的seq,表示发送下一个包,这个值就是对应的seq

func (*Socket) GetTsEcho

func (p *Socket) GetTsEcho() uint32

func (*Socket) SetLastError

func (p *Socket) SetLastError(err error)

设置最近的错误

func (*Socket) UpdateAckNum

func (p *Socket) UpdateAckNum()

func (*Socket) UpdateSeqNum

func (p *Socket) UpdateSeqNum()

更新序列号

type TCPSock

type TCPSock struct {
	Status int // TCP状态
	// TCP 信息
	SeqNum                                     uint32 // 顺序号
	AckNum                                     uint32 // 确认序列号
	RecvedSeqNum                               uint32 // 接收顺序号
	RecvedAckNum                               uint32 // 确认序列号
	DataOffset                                 uint8
	FIN, SYN, RST, PSH, ACK, URG, ECE, CWR, NS bool
	PreRecvedSignal                            int // 当前接收的信号  FIN/SYN/RST/PSH/ACK/URG/ECE/CWR/NS 分析后得到的信号
	PreSentSignal                              int // FIN/SYN/RST/PSH/ACK/URG/ECE/CWR/NS 分析后得到的信号
	Options                                    []layers.TCPOption
	IsSupportTimestamp                         bool   // 是否支持时间戳
	TsEcho                                     uint32 // 时间戳相关
	MSS                                        uint16 // 最大报文长度
	WinSize                                    uint16 // 窗口大小
	RecvdWinSize                               uint16 // 接收窗口大小
}

type UDPSock

type UDPSock struct {
	Length uint16
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL