Replace netlink with fork

This commit is contained in:
世界 2022-08-03 12:00:44 +08:00
parent 9b2841f33d
commit 9fad6b0cf3
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
7 changed files with 30 additions and 247 deletions

4
go.mod
View file

@ -3,9 +3,9 @@ module github.com/sagernet/sing-tun
go 1.18
require (
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805
github.com/sagernet/sing v0.0.0-20220730061053-a21e329a2698
github.com/vishvananda/netlink v1.1.0
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10
golang.org/x/sys v0.0.0-20220731174439-a90be440212d
gvisor.dev/gvisor v0.0.0-20220711011657-cecae2f4234d
)

10
go.sum
View file

@ -1,16 +1,14 @@
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.0.0-20220730061053-a21e329a2698 h1:wjoF4/FOwze8cN2/EvQyyuq1tzXjxNViPIoqQ7CNIb8=
github.com/sagernet/sing v0.0.0-20220730061053-a21e329a2698/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
gvisor.dev/gvisor v0.0.0-20220711011657-cecae2f4234d h1:KjI6i6P1ib9DiNdNIN8pb2TXfBewpKHf3O58cjj9vw4=

View file

@ -1,9 +1,8 @@
package tun
import (
"github.com/sagernet/netlink"
E "github.com/sagernet/sing/common/exceptions"
"github.com/vishvananda/netlink"
)
func (m *defaultInterfaceMonitor) checkUpdate() error {

View file

@ -5,10 +5,9 @@ import (
"os"
"sync"
"github.com/sagernet/netlink"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/x/list"
"github.com/vishvananda/netlink"
)
type networkUpdateMonitor struct {

View file

@ -3,9 +3,9 @@
package tun
import (
"github.com/sagernet/netlink"
E "github.com/sagernet/sing/common/exceptions"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
)

View file

@ -1,213 +0,0 @@
package tun
import (
"bytes"
"fmt"
"net/netip"
_ "unsafe"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
type Rule struct {
Priority int
Family int
Table int
Mark int
Mask int
TunID uint
Goto int
Src netip.Prefix
Dst netip.Prefix
Flow int
IifName string
OifName string
SuppressIfgroup int
SuppressPrefixLength int
Invert bool
IPProtocol int
SrcPortRange *RulePortRange
DstPortRange *RulePortRange
UIDRange *RuleUIDRange
}
func NewRule() *Rule {
return &Rule{
SuppressIfgroup: -1,
SuppressPrefixLength: -1,
Priority: -1,
Mark: -1,
Mask: -1,
Goto: -1,
Flow: -1,
IPProtocol: -1,
}
}
//go:linkname pkgHandle github.com/vishvananda/netlink.pkgHandle
var pkgHandle *netlink.Handle
//go:linkname newNetlinkRequest github.com/vishvananda/netlink.(*Handle).newNetlinkRequest
func newNetlinkRequest(h *netlink.Handle, proto, flags int) *nl.NetlinkRequest
func RuleAdd(rule *Rule) error {
req := newNetlinkRequest(pkgHandle, unix.RTM_NEWRULE, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
return ruleHandle(rule, req)
}
func RuleDel(rule *Rule) error {
req := newNetlinkRequest(pkgHandle, unix.RTM_DELRULE, unix.NLM_F_ACK)
return ruleHandle(rule, req)
}
type RulePortRange struct {
Start uint16
End uint16
}
func (pr *RulePortRange) toRtAttrData() []byte {
native := nl.NativeEndian()
b := [][]byte{make([]byte, 2), make([]byte, 2)}
native.PutUint16(b[0], pr.Start)
native.PutUint16(b[1], pr.End)
return bytes.Join(b, []byte{})
}
type RuleUIDRange struct {
Start uint32
End uint32
}
func (pr *RuleUIDRange) toRtAttrData() []byte {
native := nl.NativeEndian()
b := [][]byte{make([]byte, 4), make([]byte, 4)}
native.PutUint32(b[0], pr.Start)
native.PutUint32(b[1], pr.End)
return bytes.Join(b, []byte{})
}
func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
msg := nl.NewRtMsg()
msg.Family = unix.AF_INET
msg.Protocol = unix.RTPROT_BOOT
msg.Scope = unix.RT_SCOPE_UNIVERSE
msg.Table = unix.RT_TABLE_UNSPEC
msg.Type = unix.RTN_UNSPEC
if rule.Table >= 256 {
msg.Type = unix.FR_ACT_TO_TBL
} else if rule.Goto >= 0 {
msg.Type = unix.FR_ACT_GOTO
} else if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 {
msg.Type = unix.FR_ACT_NOP
}
if rule.Invert {
msg.Flags |= netlink.FibRuleInvert
}
if rule.Family != 0 {
msg.Family = uint8(rule.Family)
}
if rule.Table >= 0 && rule.Table < 256 {
msg.Table = uint8(rule.Table)
}
var dstFamily uint8
var rtAttrs []*nl.RtAttr
if rule.Dst.IsValid() {
msg.Dst_len = uint8(rule.Dst.Bits())
msg.Family = uint8(nl.GetIPFamily(rule.Dst.Addr().AsSlice()))
dstFamily = msg.Family
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_DST, rule.Dst.Addr().AsSlice()))
}
if rule.Src.IsValid() {
msg.Src_len = uint8(rule.Src.Bits())
msg.Family = uint8(nl.GetIPFamily(rule.Src.Addr().AsSlice()))
if dstFamily != 0 && dstFamily != msg.Family {
return fmt.Errorf("source and destination ip are not the same IP family")
}
dstFamily = msg.Family
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_SRC, rule.Src.Addr().AsSlice()))
}
req.AddData(msg)
for i := range rtAttrs {
req.AddData(rtAttrs[i])
}
native := nl.NativeEndian()
if rule.Priority >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Priority))
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
}
if rule.Mark >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Mark))
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
}
if rule.Mask >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Mask))
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
}
if rule.Flow >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Flow))
req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b))
}
if rule.TunID > 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.TunID))
req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b))
}
if rule.Table >= 256 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Table))
req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b))
}
if msg.Table > 0 {
if rule.SuppressPrefixLength >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.SuppressPrefixLength))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b))
}
if rule.SuppressIfgroup >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.SuppressIfgroup))
req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b))
}
}
if rule.IifName != "" {
req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName)))
}
if rule.OifName != "" {
req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName)))
}
if rule.Goto >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Goto))
req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b))
}
if rule.IPProtocol >= 0 {
req.AddData(nl.NewRtAttr(unix.FRA_IP_PROTO, []byte{byte(rule.IPProtocol)}))
}
if rule.SrcPortRange != nil {
b := rule.SrcPortRange.toRtAttrData()
req.AddData(nl.NewRtAttr(unix.FRA_SPORT_RANGE, b))
}
if rule.DstPortRange != nil {
b := rule.DstPortRange.toRtAttrData()
req.AddData(nl.NewRtAttr(unix.FRA_DPORT_RANGE, b))
}
if rule.UIDRange != nil {
b := rule.UIDRange.toRtAttrData()
req.AddData(nl.NewRtAttr(unix.FRA_UID_RANGE, b))
}
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}

View file

@ -4,9 +4,9 @@ import (
"net"
"net/netip"
"github.com/sagernet/netlink"
E "github.com/sagernet/sing/common/exceptions"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
@ -127,61 +127,61 @@ func (t *NativeTun) routes(tunLink netlink.Link) []netlink.Route {
return routes
}
func (t *NativeTun) rules() []*Rule {
var rules []*Rule
func (t *NativeTun) rules() []*netlink.Rule {
var rules []*netlink.Rule
priority := 9000
it := NewRule()
it := netlink.NewRule()
it.Priority = priority
it.Invert = true
it.UIDRange = &RuleUIDRange{Start: 0, End: 0xFFFFFFFF - 1}
it.UIDRange = netlink.NewRuleUIDRange(0, 0xFFFFFFFF-1)
it.Goto = 9100
rules = append(rules, it)
priority++
if t.inet4Address.IsValid() {
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.Dst = t.inet4Address.Masked()
it.Table = tunTableIndex
rules = append(rules, it)
priority++
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.IPProtocol = unix.IPPROTO_ICMP
it.IPProto = unix.IPPROTO_ICMP
it.Goto = 9100
rules = append(rules, it)
priority++
}
if t.inet6Address.IsValid() {
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.Dst = t.inet6Address.Masked()
it.Table = tunTableIndex
rules = append(rules, it)
priority++
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.IPProtocol = unix.IPPROTO_ICMPV6
it.IPProto = unix.IPPROTO_ICMPV6
it.Goto = 9100
rules = append(rules, it)
priority++
}
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.DstPortRange = &RulePortRange{Start: 53, End: 53}
it.Dport = netlink.NewRulePortRange(53, 53)
it.Table = unix.RT_TABLE_MAIN
it.SuppressPrefixLength = 0
it.SuppressPrefixlen = 0
rules = append(rules, it)
priority++
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.Invert = true
it.IifName = "lo"
@ -189,7 +189,7 @@ func (t *NativeTun) rules() []*Rule {
rules = append(rules, it)
priority++
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = netip.PrefixFrom(netip.IPv4Unspecified(), 32)
@ -198,7 +198,7 @@ func (t *NativeTun) rules() []*Rule {
priority++
if t.inet4Address.IsValid() {
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = t.inet4Address.Masked()
@ -208,7 +208,7 @@ func (t *NativeTun) rules() []*Rule {
}
if t.inet6Address.IsValid() {
it = NewRule()
it = netlink.NewRule()
it.Priority = priority
it.IifName = "lo"
it.Src = t.inet6Address.Masked()
@ -217,7 +217,7 @@ func (t *NativeTun) rules() []*Rule {
priority++
}
it = NewRule()
it = netlink.NewRule()
it.Priority = 9100
rules = append(rules, it)
@ -232,7 +232,7 @@ func (t *NativeTun) setRoute(tunLink netlink.Link) error {
}
}
for i, rule := range t.rules() {
err := RuleAdd(rule)
err := netlink.RuleAdd(rule)
if err != nil {
return E.Cause(err, "add rule ", i, "/", len(t.rules()))
}
@ -257,7 +257,7 @@ func (t *NativeTun) unsetRoute0(tunLink netlink.Link) error {
}
}
for _, rule := range t.rules() {
err := RuleDel(rule)
err := netlink.RuleDel(rule)
if err != nil {
errors = append(errors, err)
}