ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
175
packages/mesh-init/abi.go
Normal file
175
packages/mesh-init/abi.go
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
xtHeader = 32
|
||||
ruleHead = 112
|
||||
)
|
||||
|
||||
type tableInfo struct {
|
||||
Name [32]byte
|
||||
Valid uint32
|
||||
Hooks [5]uint32
|
||||
Underflow [5]uint32
|
||||
Count uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
type replaceHead struct {
|
||||
Name [32]byte
|
||||
Valid uint32
|
||||
Count uint32
|
||||
Size uint32
|
||||
Hooks [5]uint32
|
||||
Underflow [5]uint32
|
||||
OldCount uint32
|
||||
Address uint64
|
||||
}
|
||||
|
||||
type ipMatch struct {
|
||||
Addresses [4]uint32
|
||||
In [16]byte
|
||||
Out [16]byte
|
||||
InMask [16]byte
|
||||
OutMask [16]byte
|
||||
Protocol uint16
|
||||
Flags uint8
|
||||
Inverse uint8
|
||||
}
|
||||
|
||||
type counter struct {
|
||||
Packets uint64
|
||||
Bytes uint64
|
||||
}
|
||||
|
||||
type ruleHeader struct {
|
||||
IP ipMatch
|
||||
Cache uint32
|
||||
Target uint16
|
||||
Next uint16
|
||||
From uint32
|
||||
Counters counter
|
||||
}
|
||||
|
||||
type replacement struct {
|
||||
data []byte
|
||||
counters []counter
|
||||
pins runtime.Pinner
|
||||
}
|
||||
|
||||
func encode(value any) []byte {
|
||||
data, err := binary.Append(nil, binary.NativeEndian, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func size16(size int) uint16 {
|
||||
if size < 0 || size > math.MaxUint16 {
|
||||
panic("iptables size exceeds uint16")
|
||||
}
|
||||
return uint16(size)
|
||||
}
|
||||
|
||||
func size32(size int) uint32 {
|
||||
if size < 0 || uint64(size) > math.MaxUint32 {
|
||||
panic("iptables size exceeds uint32")
|
||||
}
|
||||
return uint32(size)
|
||||
}
|
||||
|
||||
func extension(name string, revision uint8, data []byte) []byte {
|
||||
size := (xtHeader + len(data) + 7) &^ 7
|
||||
header := struct {
|
||||
Size uint16
|
||||
Name [29]byte
|
||||
Revision uint8
|
||||
}{Size: size16(size), Revision: revision}
|
||||
copy(header.Name[:], name)
|
||||
result := append(encode(header), data...)
|
||||
return append(result, make([]byte, size-len(result))...)
|
||||
}
|
||||
|
||||
func accept() []byte {
|
||||
return extension("", 0, encode(int32(-2)))
|
||||
}
|
||||
|
||||
func redirect(port uint16) []byte {
|
||||
rangeInfo := struct {
|
||||
Count uint32
|
||||
Flags uint32
|
||||
IPs [2]uint32
|
||||
Ports [4]byte
|
||||
}{Count: 1, Flags: 2}
|
||||
binary.BigEndian.PutUint16(rangeInfo.Ports[:2], port)
|
||||
binary.BigEndian.PutUint16(rangeInfo.Ports[2:], port)
|
||||
return extension("REDIRECT", 0, encode(rangeInfo))
|
||||
}
|
||||
|
||||
func tcp(port uint16) []byte {
|
||||
return extension("tcp", 0, encode(struct {
|
||||
Source [2]uint16
|
||||
Dest [2]uint16
|
||||
Flags [4]uint8
|
||||
}{Source: [2]uint16{0, math.MaxUint16}, Dest: [2]uint16{port, port}}))
|
||||
}
|
||||
|
||||
func owner(uid uint32) []byte {
|
||||
return extension("owner", 1, encode(struct {
|
||||
UID [2]uint32
|
||||
GID [2]uint32
|
||||
Match uint8
|
||||
Invert uint8
|
||||
Pad [2]byte
|
||||
}{UID: [2]uint32{uid, uid}, Match: 1}))
|
||||
}
|
||||
|
||||
func rule(protocol uint16, match, target []byte, loopback bool) []byte {
|
||||
header := ruleHeader{
|
||||
IP: ipMatch{Protocol: protocol},
|
||||
Target: size16(ruleHead + len(match)),
|
||||
Next: size16(ruleHead + len(match) + len(target)),
|
||||
}
|
||||
if loopback {
|
||||
copy(header.IP.Out[:], "lo")
|
||||
header.IP.OutMask[0], header.IP.OutMask[1], header.IP.OutMask[2] = 255, 255, 255
|
||||
}
|
||||
return append(append(encode(header), match...), target...)
|
||||
}
|
||||
|
||||
func table(value config, count uint32, address uint64) []byte {
|
||||
header := replaceHead{Valid: 27, OldCount: count, Address: address}
|
||||
copy(header.Name[:], "nat")
|
||||
var body []byte
|
||||
add := func(data []byte) {
|
||||
body = append(body, data...)
|
||||
header.Count++
|
||||
}
|
||||
for _, hook := range []int{0, 1, 3, 4} {
|
||||
header.Hooks[hook] = size32(len(body))
|
||||
switch hook {
|
||||
case 0:
|
||||
for _, port := range value.exclude {
|
||||
add(rule(6, tcp(port), accept(), false))
|
||||
}
|
||||
add(rule(6, nil, redirect(value.inbound), false))
|
||||
case 3:
|
||||
add(rule(0, owner(value.proxyUID), accept(), false))
|
||||
add(rule(0, nil, accept(), true))
|
||||
add(rule(6, nil, redirect(value.outbound), false))
|
||||
}
|
||||
header.Underflow[hook] = size32(len(body))
|
||||
add(rule(0, nil, accept(), false))
|
||||
}
|
||||
var label [30]byte
|
||||
copy(label[:], "ERROR")
|
||||
add(rule(0, nil, extension("ERROR", 0, label[:]), false))
|
||||
header.Size = size32(len(body))
|
||||
return append(encode(header), body...)
|
||||
}
|
||||
Loading…
Reference in a new issue