Add netns support

This commit is contained in:
世界 2026-07-11 00:57:57 +08:00
parent d0d4ebd8db
commit 994d6ccdbf
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
7 changed files with 220 additions and 80 deletions

View file

@ -51,37 +51,38 @@ type NativeTun struct {
}
func New(options Options) (Tun, error) {
var nativeTun *NativeTun
if options.FileDescriptor == 0 {
tunFd, err := open(options.Name, options.GSO)
if err != nil {
return nil, E.Cause(err, "open tun")
}
tunLink, err := netlink.LinkByName(options.Name)
if err != nil {
return nil, E.Errors(err, unix.Close(tunFd))
}
nativeTun = &NativeTun{
tunFd: tunFd,
tunFile: os.NewFile(uintptr(tunFd), "tun"),
options: options,
}
err = nativeTun.configure(tunLink)
if err != nil {
return nil, E.Errors(err, unix.Close(tunFd))
}
} else {
nativeTun = &NativeTun{
tunFd: options.FileDescriptor,
tunFile: os.NewFile(uintptr(options.FileDescriptor), "tun"),
options: options,
}
if options.GSO {
err := nativeTun.enableGSO()
return execInNetworkNamespace(options.NetNs, func() (Tun, error) {
tunFd, err := open(options.Name, options.GSO)
if err != nil {
if options.Logger != nil {
options.Logger.Warn(err)
}
return nil, E.Cause(err, "open tun")
}
tunLink, err := netlink.LinkByName(options.Name)
if err != nil {
return nil, E.Errors(err, unix.Close(tunFd))
}
nativeTun := &NativeTun{
tunFd: tunFd,
tunFile: os.NewFile(uintptr(tunFd), "tun"),
options: options,
}
err = nativeTun.configure(tunLink)
if err != nil {
return nil, E.Errors(err, unix.Close(tunFd))
}
return nativeTun, nil
})
}
nativeTun := &NativeTun{
tunFd: options.FileDescriptor,
tunFile: os.NewFile(uintptr(options.FileDescriptor), "tun"),
options: options,
}
if options.GSO {
err := nativeTun.enableGSO()
if err != nil {
if options.Logger != nil {
options.Logger.Warn(err)
}
}
}
@ -290,10 +291,10 @@ func (t *NativeTun) Name() (string, error) {
func (t *NativeTun) Start() error {
if t.options.FileDescriptor == 0 {
if !t.options.EXP_ExternalConfiguration {
if !t.options.EXP_ExternalConfiguration && t.options.NetNs == "" {
t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name)
}
err := t.start()
err := runInNetworkNamespace(t.options.NetNs, t.start)
if err != nil {
return err
}
@ -354,7 +355,7 @@ func (t *NativeTun) start() error {
return E.Cause(err, "set rules")
}
if t.options.DNSMode != DNSModeDisabled {
if t.options.DNSMode != DNSModeDisabled && t.options.NetNs == "" {
err = t.setSearchDomainForSystemdResolved()
if err != nil {
return E.Cause(err, "set search domain")
@ -374,11 +375,13 @@ func (t *NativeTun) Close() error {
if t.options.EXP_ExternalConfiguration {
return common.Close(common.PtrOrNil(t.tunFile))
}
if t.options.DNSMode != DNSModeDisabled {
if t.options.DNSMode != DNSModeDisabled && t.options.NetNs == "" {
t.unsetSearchDomainForSystemdResolved()
}
t.unsetAddresses()
return E.Errors(t.unsetRoute(), t.unsetRules(), common.Close(common.PtrOrNil(t.tunFile)))
return E.Errors(runInNetworkNamespace(t.options.NetNs, func() error {
t.unsetAddresses()
return E.Errors(t.unsetRoute(), t.unsetRules())
}), common.Close(common.PtrOrNil(t.tunFile)))
}
func (t *NativeTun) Read(p []byte) (n int, err error) {
@ -625,16 +628,18 @@ func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error {
t.options = tunOptions
return nil
}
tunLink, err := netlink.LinkByName(t.options.Name)
if err != nil {
return E.Cause(err, "find tun interface")
}
err = t.unsetRoute0(tunLink)
if err != nil {
return E.Cause(err, "unset old routes")
}
t.options = tunOptions
return t.setRoute(tunLink)
return runInNetworkNamespace(t.options.NetNs, func() error {
tunLink, err := netlink.LinkByName(t.options.Name)
if err != nil {
return E.Cause(err, "find tun interface")
}
err = t.unsetRoute0(tunLink)
if err != nil {
return E.Cause(err, "unset old routes")
}
t.options = tunOptions
return t.setRoute(tunLink)
})
}
func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) {