Add DNS mode
This commit is contained in:
parent
3c7d6ad82f
commit
47bdde06c3
4 changed files with 103 additions and 58 deletions
|
|
@ -675,7 +675,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft
|
|||
nftablesCreateExcludeDestinationIPSet(nft, table, chain, inet6RouteExcludeAddress.ID, inet6RouteExcludeAddress.Name, nftables.TableFamilyIPv6, false)
|
||||
}
|
||||
|
||||
if !r.tunOptions.EXP_DisableDNSHijack && ((chain.Hooknum == nftables.ChainHookPrerouting && chain.Type == nftables.ChainTypeNAT) ||
|
||||
if r.tunOptions.DNSModeOrDefault() == DNSModeHijack && ((chain.Hooknum == nftables.ChainHookPrerouting && chain.Type == nftables.ChainTypeNAT) ||
|
||||
(r.tunOptions.AutoRedirectMarkMode && chain.Hooknum == nftables.ChainHookOutput && chain.Type == nftables.ChainTypeNAT)) {
|
||||
if r.enableIPv4 {
|
||||
err := r.nftablesCreateDNSHijackRulesForFamily(nft, table, chain, nftables.TableFamilyIPv4, 5, "inet4_local_address_set")
|
||||
|
|
@ -1050,23 +1050,19 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily(
|
|||
if err != nil {
|
||||
return E.Cause(err, "add dns protocol set")
|
||||
}
|
||||
dnsServer := common.Find(r.tunOptions.DNSServers, func(it netip.Addr) bool {
|
||||
return it.Is4() == (family == nftables.TableFamilyIPv4)
|
||||
})
|
||||
if !dnsServer.IsValid() {
|
||||
if family == nftables.TableFamilyIPv4 {
|
||||
if HasNextAddress(r.tunOptions.Inet4Address[0], 1) {
|
||||
dnsServer = r.tunOptions.Inet4Address[0].Addr().Next()
|
||||
}
|
||||
} else {
|
||||
if HasNextAddress(r.tunOptions.Inet6Address[0], 1) {
|
||||
dnsServer = r.tunOptions.Inet6Address[0].Addr().Next()
|
||||
}
|
||||
}
|
||||
var dnsServers []netip.Addr
|
||||
if family == nftables.TableFamilyIPv4 {
|
||||
dnsServers, err = r.tunOptions.Inet4DNSAddress()
|
||||
} else {
|
||||
dnsServers, err = r.tunOptions.Inet6DNSAddress()
|
||||
}
|
||||
if !dnsServer.IsValid() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dnsServers) == 0 {
|
||||
return nil
|
||||
}
|
||||
dnsServer := dnsServers[0]
|
||||
exprs := []expr.Any{
|
||||
&expr.Meta{
|
||||
Key: expr.MetaKeyNFPROTO,
|
||||
|
|
|
|||
62
tun.go
62
tun.go
|
|
@ -9,8 +9,10 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
|
|
@ -68,6 +70,12 @@ const (
|
|||
DefaultIPRoute2AutoRedirectFallbackRuleIndex = 32768
|
||||
)
|
||||
|
||||
const (
|
||||
DNSModeDisabled = "disabled"
|
||||
DNSModeNative = "native"
|
||||
DNSModeHijack = "hijack"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Name string
|
||||
Inet4Address []netip.Prefix
|
||||
|
|
@ -78,7 +86,8 @@ type Options struct {
|
|||
InterfaceScope bool
|
||||
Inet4Gateway netip.Addr
|
||||
Inet6Gateway netip.Addr
|
||||
DNSServers []netip.Addr
|
||||
DNSMode string
|
||||
DNSAddress []netip.Addr
|
||||
IPRoute2TableIndex int
|
||||
IPRoute2RuleIndex int
|
||||
IPRoute2AutoRedirectFallbackRuleIndex int
|
||||
|
|
@ -124,6 +133,57 @@ type Options struct {
|
|||
EXP_SendMsgX bool
|
||||
}
|
||||
|
||||
func (o *Options) DNSModeOrDefault() string {
|
||||
if o.DNSMode == "" {
|
||||
return DNSModeHijack
|
||||
}
|
||||
return o.DNSMode
|
||||
}
|
||||
|
||||
func (o *Options) DNSServerAddress() ([]netip.Addr, error) {
|
||||
inet4DNS, err := o.Inet4DNSAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inet6DNS, err := o.Inet6DNSAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(inet4DNS, inet6DNS...), nil
|
||||
}
|
||||
|
||||
func (o *Options) Inet4DNSAddress() ([]netip.Addr, error) {
|
||||
if len(o.Inet4Address) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(o.DNSAddress) > 0 {
|
||||
return common.Filter(o.DNSAddress, netip.Addr.Is4), nil
|
||||
}
|
||||
if HasNextAddress(o.Inet4Address[0], 1) {
|
||||
return []netip.Addr{o.Inet4Address[0].Addr().Next()}, nil
|
||||
}
|
||||
if !(len(o.Inet6Address) > 0 && HasNextAddress(o.Inet6Address[0], 1)) {
|
||||
return nil, E.New("no IPv4 server configured and no usable next address in ", o.Inet6Address[0], " for DNS")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (o *Options) Inet6DNSAddress() ([]netip.Addr, error) {
|
||||
if len(o.Inet6Address) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(o.DNSAddress) > 0 {
|
||||
return common.Filter(o.DNSAddress, netip.Addr.Is6), nil
|
||||
}
|
||||
if HasNextAddress(o.Inet6Address[0], 1) {
|
||||
return []netip.Addr{o.Inet6Address[0].Addr().Next()}, nil
|
||||
}
|
||||
if !(len(o.Inet4Address) > 0 && HasNextAddress(o.Inet4Address[0], 1)) {
|
||||
return nil, E.New("no IPv6 server configured and no usable next address in ", o.Inet6Address[0], " for DNS")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (o *Options) Inet4GatewayAddr() netip.Addr {
|
||||
if o.Inet4Gateway.IsValid() {
|
||||
return o.Inet4Gateway
|
||||
|
|
|
|||
38
tun_linux.go
38
tun_linux.go
|
|
@ -354,7 +354,12 @@ func (t *NativeTun) start() error {
|
|||
return E.Cause(err, "set rules")
|
||||
}
|
||||
|
||||
t.setSearchDomainForSystemdResolved()
|
||||
if t.options.DNSMode != DNSModeDisabled {
|
||||
err = t.setSearchDomainForSystemdResolved()
|
||||
if err != nil {
|
||||
return E.Cause(err, "set search domain")
|
||||
}
|
||||
}
|
||||
|
||||
if t.options.AutoRoute && runtime.GOOS == "android" {
|
||||
t.interfaceCallback = t.options.InterfaceMonitor.RegisterCallback(t.routeUpdate)
|
||||
|
|
@ -369,7 +374,9 @@ func (t *NativeTun) Close() error {
|
|||
if t.options.EXP_ExternalConfiguration {
|
||||
return common.Close(common.PtrOrNil(t.tunFile))
|
||||
}
|
||||
t.unsetSearchDomainForSystemdResolved()
|
||||
if t.options.DNSMode != DNSModeDisabled {
|
||||
t.unsetSearchDomainForSystemdResolved()
|
||||
}
|
||||
t.unsetAddresses()
|
||||
return E.Errors(t.unsetRoute(), t.unsetRules(), common.Close(common.PtrOrNil(t.tunFile)))
|
||||
}
|
||||
|
|
@ -1190,37 +1197,24 @@ func (t *NativeTun) routeUpdate(_ *control.Interface, flags int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *NativeTun) setSearchDomainForSystemdResolved() {
|
||||
if t.options.EXP_DisableDNSHijack {
|
||||
return
|
||||
}
|
||||
func (t *NativeTun) setSearchDomainForSystemdResolved() error {
|
||||
ctlPath, err := exec.LookPath("resolvectl")
|
||||
if err != nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
dnsServer := t.options.DNSServers
|
||||
if len(dnsServer) == 0 {
|
||||
if len(t.options.Inet4Address) > 0 && HasNextAddress(t.options.Inet4Address[0], 1) {
|
||||
dnsServer = append(dnsServer, t.options.Inet4Address[0].Addr().Next())
|
||||
}
|
||||
if len(t.options.Inet6Address) > 0 && HasNextAddress(t.options.Inet6Address[0], 1) {
|
||||
dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next())
|
||||
}
|
||||
}
|
||||
if len(dnsServer) == 0 {
|
||||
return
|
||||
dnsAddress, err := t.options.DNSServerAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
_ = shell.Exec(ctlPath, "domain", t.options.Name, "~.").Run()
|
||||
_ = shell.Exec(ctlPath, "default-route", t.options.Name, "true").Run()
|
||||
_ = shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsServer, netip.Addr.String)...)...).Run()
|
||||
_ = shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsAddress, netip.Addr.String)...)...).Run()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *NativeTun) unsetSearchDomainForSystemdResolved() {
|
||||
if t.options.EXP_DisableDNSHijack {
|
||||
return
|
||||
}
|
||||
ctlPath, err := exec.LookPath("resolvectl")
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/sagernet/sing-tun/internal/winipcfg"
|
||||
"github.com/sagernet/sing-tun/internal/winsys"
|
||||
"github.com/sagernet/sing-tun/internal/wintun"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/windnsapi"
|
||||
|
||||
|
|
@ -81,16 +80,14 @@ func (t *NativeTun) configure() error {
|
|||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 address")
|
||||
}
|
||||
if t.options.AutoRoute && !t.options.EXP_DisableDNSHijack {
|
||||
dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is4)
|
||||
if len(dnsServers) == 0 && HasNextAddress(t.options.Inet4Address[0], 1) {
|
||||
dnsServers = []netip.Addr{t.options.Inet4Address[0].Addr().Next()}
|
||||
if t.options.AutoRoute && t.options.DNSModeOrDefault() != DNSModeDisabled {
|
||||
dnsServers, err := t.options.Inet4DNSAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dnsServers) > 0 {
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 dns")
|
||||
}
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), dnsServers, nil)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 dns")
|
||||
}
|
||||
} else {
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET), nil, nil)
|
||||
|
|
@ -104,16 +101,14 @@ func (t *NativeTun) configure() error {
|
|||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 address")
|
||||
}
|
||||
if t.options.AutoRoute && !t.options.EXP_DisableDNSHijack {
|
||||
dnsServers := common.Filter(t.options.DNSServers, netip.Addr.Is6)
|
||||
if len(dnsServers) == 0 && HasNextAddress(t.options.Inet6Address[0], 1) {
|
||||
dnsServers = []netip.Addr{t.options.Inet6Address[0].Addr().Next()}
|
||||
if t.options.AutoRoute && t.options.DNSModeOrDefault() != DNSModeDisabled {
|
||||
dnsServers, err := t.options.Inet6DNSAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dnsServers) > 0 {
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 dns")
|
||||
}
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), dnsServers, nil)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 dns")
|
||||
}
|
||||
} else {
|
||||
err = luid.SetDNS(winipcfg.AddressFamily(windows.AF_INET6), nil, nil)
|
||||
|
|
@ -334,7 +329,7 @@ func (t *NativeTun) Start() error {
|
|||
}
|
||||
}
|
||||
|
||||
if !t.options.EXP_DisableDNSHijack {
|
||||
if t.options.DNSModeOrDefault() == DNSModeHijack {
|
||||
blockDNSCondition := make([]winsys.FWPM_FILTER_CONDITION0, 1)
|
||||
blockDNSCondition[0].FieldKey = winsys.FWPM_CONDITION_IP_REMOTE_PORT
|
||||
blockDNSCondition[0].MatchType = winsys.FWP_MATCH_EQUAL
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue