给数据包设定mark,最常用的场景就是策略路由了,ip rule根据mark来决定数据包的路由方式,以下是经过验证的,go语言给tcp和udp数据包设定mark的方式。
TCP
1
2
3
4
5
6
7
8
9
10
11
|
dialer := &net.Dialer{
Control: func(_, _ string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
ex := setSocketMark(int(fd), xc.Mark.Value)
if ex != nil {
logf("net dialer set mark error: %s", ex)
}
})
},
}
rc, e = dialer.Dial("tcp", target)
|
TCP可以在net.Dialer的Control这个方法内处理。
UDP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func setConnMark(conn interface{}, value int) (e error) {
var f *os.File
switch conn.(type) {
case *net.TCPConn:
f, e = conn.(*net.TCPConn).File()
case *net.UDPConn:
f, e = conn.(*net.UDPConn).File()
default:
return fmt.Errorf("not support conn(%v), with type(%T)", conn, conn)
}
if e != nil {
return
}
defer f.Close()
return setSocketMark(int(f.Fd()), value)
}
func setSocketMark(fd int, value int) (e error) {
return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, value)
}
|
UDP通过调用上方提供的setConnMark()
函数来处理。