golang 监听ip数据包(golang纯享版)
【注】本机编译运行平台为linux,如需测试代码请移至linux平台进行代码测试
本文以ip4 作为案例进行包抓取示范,ip6抓取与ip4方式异曲同工,可自行举一反三得出
第一步,通过wireshark抓包拿到ip4下的tcp/udp包,通过wireshark可视化我们可以很容易找到我们需要的源/目的地址信息所在ip包字节数. 这里两张截图,一张ip4,一张ip6的


第二步,编写我们秘制的简易抓包工具,此处以直接输出来源和去向地址为例,自己可以根据需求做更改
package inet
import (
"encoding/binary"
"fmt"
"strconv"
"syscall"
"unsafe"
)
func reverse(b []byte) {
var (
mid uint8
blen = len(b)
)
if blen > 1 {
for i := 0; i < blen/2; i++ {
mid = b[i]
b[i] = b[blen-i-1]
b[blen-i-1] = mid
}
}
}
//主机字节序变网络字节序
func htons[t uint | uint16 | uint32 | uint64](t t) t {
var (
b []byte = make([]byte, unsafe.sizeof(t))
ptr *t = (*t)(unsafe.pointer(&b[0]))
)
*ptr = t
reverse(b)
return *ptr
}
//ip包必选,ip6自行根据wireshark进行编写,此处ip4为例
type ipheader struct {
version_and_len uint8//前4个bit为version(4 ip4,6 ip6),后bit个字节为首部length xxxx xxxx
differnetialtedservice uint8
tot_len uint16
id uint16
flag_and_seek uint16//前3bit 为flag后面13bit为seek
ttl uint8
protocol uint8
checksum uint16
source uint32
dest uint32
}
type portinfo struct {
source uint16
dest uint16
}
var (
__ip_default ipheader
ipheader_size = int(unsafe.sizeof(__ip_default))
)
func watch(watcher func([]byte, int)) error {
//socket af_packet 会抓取全部网卡的ip数据包,如需监听特定的网卡请自行判断
fd, _, err_ := syscall.syscall(syscall.sys_socket, syscall.af_packet, syscall.sock_dgram, uintptr(htons[uint16](syscall.eth_p_ip)))
if int(fd) < 0 {
return err_
}
ifd := int(fd)
var (
buff []byte = make([]byte, 512)
lang int
err error
)
defer syscall.close(ifd)
fmt.println("start watch raw stream", ifd)
for {
lang, _, err = syscall.recvfrom(ifd, buff, 0)
if lang <= 0 {
break
}
watcher(buff, lang)
}
return err
}
//输出所有来源去向
func print_info(info []byte, size int) {
if size <= ipheader_size {
return
}
var (
ipheader *ipheader = (*ipheader)(unsafe.pointer(&info[0]))
portinfo *portinfo
)
if size > ipheader_size+4 {
portinfo = (*portinfo)(unsafe.pointer(&info[ipheader_size]))
fmt.printf("src %s:%d dst %s:%d\n", raw2string(ipheader.source), portinfo.source, raw2string(ipheader.dest), portinfo.dest)
} else {
fmt.printf("src %s dst %s\n", raw2string(ipheader.source), raw2string(ipheader.dest))
}
}
func raw2string(src uint32) string {
raw := make([]byte, 4)
binary.littleendian.putuint32(raw, src)
return strconv.formatuint(uint64(raw[0]), 10) + "." + strconv.formatuint(uint64(raw[1]), 10) + "." + strconv.formatuint(uint64(raw[2]), 10) + "." + strconv.formatuint(uint64(raw[3]), 10)
}
func print_info() func([]byte, int) {
return print_info
}
测试主函数
func main() {
fmt.fprintln(os.stderr, inet.watch(inet.print_info()))
}
效果

以上就是golang监听ip数据包的实现步骤(golang纯享版)的详细内容,更多关于golang监听ip数据包的资料请关注代码网其它相关文章!
发表评论