Skip to content

Commit

Permalink
reduce dns query
Browse files Browse the repository at this point in the history
  • Loading branch information
xjdrew committed Dec 27, 2023
1 parent 754c81e commit 649d14c
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 35 deletions.
8 changes: 4 additions & 4 deletions cmd/kone/test.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ manager-addr = "0.0.0.0:9200"
# log level
# log-level = 'verbose, info, notify, or warning'

# upstream dns
# DEFAULT VALUE: 114.114.114.114,223.5.5.5
dns-server = 1.1.1.1,8.8.8.8

# nat config
[Core]
# outbound network interface
Expand Down Expand Up @@ -39,6 +35,10 @@ network = 10.192.0.1/16
# dns-read-timeout = 5
# dns-write-timeout = 5

# upstream dns
# DEFAULT VALUE: 114.114.114.114,223.5.5.5
dns-server = 114.114.114.114,8.8.8.8

[Proxy]
# define a http proxy named "Proxy1"
Proxy1 = http://example.com:23188
Expand Down
49 changes: 22 additions & 27 deletions dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
DnsDefaultWriteTimeout = 5
)

var errResolve = errors.New("resolve error")
var ErrResolve = errors.New("resolve timeout")

type Dns struct {
one *One
Expand All @@ -33,6 +33,14 @@ type Dns struct {
nameservers []string
}

// query synchronously
func (d *Dns) Resolve(domain string) (*dns.Msg, error) {
r := new(dns.Msg)
r.SetQuestion(dns.Fqdn(domain), dns.TypeA)

return d.resolve(r)
}

func (d *Dns) resolve(r *dns.Msg) (*dns.Msg, error) {
var wg sync.WaitGroup
msgCh := make(chan *dns.Msg, 1)
Expand All @@ -48,7 +56,8 @@ func (d *Dns) resolve(r *dns.Msg) (*dns.Msg, error) {
return
}

if r.Rcode == dns.RcodeServerFailure {
// remove this code
if r.Rcode != dns.RcodeSuccess {
logger.Debugf("[dns] resolve %s on %s failed: code %d", qname, ns, r.Rcode)
return
}
Expand Down Expand Up @@ -82,52 +91,39 @@ func (d *Dns) resolve(r *dns.Msg) (*dns.Msg, error) {
case r := <-msgCh:
return r, nil
default:
logger.Errorf("[dns] query %s failed", qname)
return nil, errResolve
logger.Errorf("[dns] query %s timeout", qname)
return nil, ErrResolve
}
}

func (d *Dns) fillRealIP(record *DomainRecord, r *dns.Msg) {
// resolve
msg, err := d.resolve(r)
if err != nil || len(msg.Answer) == 0 {
return
}
record.SetRealIP(msg)
}

func (d *Dns) doIPv4Query(r *dns.Msg) (*dns.Msg, error) {
one := d.one

domain := dnsutil.TrimDomainName(r.Question[0].Name, ".")
// if is a non-proxy-domain
// short circuit: non proxy
if one.dnsTable.IsNonProxyDomain(domain) {
return d.resolve(r)
}

// if have already hijacked
// short circuit: proxy
record := one.dnsTable.Get(domain)
if record != nil {
return record.Answer(r), nil
}

// match by domain
proxy := one.rule.Proxy(domain)

// if domain use proxy
if proxy != "DIRECT" {
record := one.dnsTable.Set(domain, proxy)
go d.fillRealIP(record, r) // why?
return record.Answer(r), nil
}

// resolve
// match by IP & CNAME
msg, err := d.resolve(r)
if err != nil || len(msg.Answer) == 0 {
return msg, err
}

// try match by cname and ip
for _, item := range msg.Answer {
switch answer := item.(type) {
case *dns.A:
Expand All @@ -147,18 +143,17 @@ func (d *Dns) doIPv4Query(r *dns.Msg) (*dns.Msg, error) {
}
}

// if ip use proxy
// if IP or CNAME use proxy
if proxy != "DIRECT" {
record := one.dnsTable.Set(domain, proxy)
record.SetRealIP(msg)
return record.Answer(r), nil
} else {
// set domain as a non-proxy-domain
one.dnsTable.SetNonProxyDomain(domain, msg.Answer[0].Header().Ttl)
// final
return msg, err
}

// set domain as a non-proxy-domain
one.dnsTable.SetNonProxyDomain(domain, msg.Answer[0].Header().Ttl)

// final
return msg, err
}

func isIPv4Query(q dns.Question) bool {
Expand Down
2 changes: 2 additions & 0 deletions manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ table th.title {
{{template "header" .}}
<h2>Current State</h2>
<ul>
<li>Dns server: {{.DnsServer}}</li>
<li>Active entries: {{.ActiveEntries}}</li>
<li>Expired entries:{{.ExpiredEntries}}</li>
</ul>
Expand Down Expand Up @@ -357,6 +358,7 @@ func (m *Manager) dnsHandle(w io.Writer, r *http.Request) error {

return m.tmpl.ExecuteTemplate(w, "dns", map[string]interface{}{
"Title": "dns cache",
"DnsServer": strings.Join(m.one.dns.nameservers, ","),
"ActiveEntries": activeEntries,
"ExpiredEntries": expiredEntires,
"Now": now,
Expand Down
6 changes: 5 additions & 1 deletion misc/windows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

## 预设条件
1. 安装 tap-windows (NDIS 6)

[tap-windows](https://community.openvpn.net/openvpn/wiki/GettingTapWindows)
[直接下载](https://build.openvpn.net/downloads/releases/tap-windows-9.21.0.exe)

2. 配置防火墙,允许kone重定向连接
使用管理员权限启动 PowerShell,执行`update-firewall-rules.ps1`

>>> 请注意修改 `update-firewall-rules.ps1` 脚本中 Program 参数为kone实际路径。
> 请注意修改 `update-firewall-rules.ps1` 脚本中 Program 参数为kone实际路径。
> 关于Windows防火墙的更多信息,参考:
> * [Manage Windows Firewall with the command line](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/configure-with-command-line?tabs=powershell)
> * [NetSecurity](https://learn.microsoft.com/en-us/powershell/module/netsecurity/?view=windowsserver2022-ps)
3. 编译&运行kone方式同linux
2 changes: 1 addition & 1 deletion proxies.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type Proxies struct {
}

func (p *Proxies) Dial(pname string, addr string) (net.Conn, error) {
logger.Debugf("[proxy] dail addr:%s by proxy:%s", addr, pname)
logger.Debugf("[proxy] dail host %s by proxy %s", addr, pname)
dialer := p.proxies[pname]
if dialer != nil {
return dialer.Dial("tcp", addr)
Expand Down
2 changes: 1 addition & 1 deletion rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (rule *Rule) Proxy(val interface{}) string {
for _, pattern := range rule.patterns {
if pattern.Match(val) {
proxy := pattern.Proxy()
logger.Debugf("[rule match] %v, proxy %q", val, proxy)
logger.Debugf("[rule match] %v, proxy %s", val, proxy)
return proxy
}
}
Expand Down
17 changes: 16 additions & 1 deletion udp_relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type UDPRelay struct {
tunnels map[string]*UDPTunnel
}

// bypass udp packet
func (r *UDPRelay) grabTunnel(localConn *net.UDPConn, cliaddr *net.UDPAddr) *UDPTunnel {
r.lock.Lock()
defer r.lock.Unlock()
Expand All @@ -71,9 +72,23 @@ func (r *UDPRelay) grabTunnel(localConn *net.UDPConn, cliaddr *net.UDPAddr) *UDP
return nil
}
record := r.one.dnsTable.GetByIP(session.dstIP)
if record == nil || record.RealIP == nil {
if record == nil { // by IP-CIDR rule
return nil
}

if record.RealIP == nil {
// try resolve real ip
msg, err := r.one.dns.Resolve(record.Hostname)
if err == nil {
record.SetRealIP(msg)
}

if record.RealIP == nil {
// resolve real ip failed
return nil
}
}

srvaddr := &net.UDPAddr{IP: record.RealIP, Port: int(session.dstPort)}
remoteConn, err := net.DialUDP("udp", nil, srvaddr)
if err != nil {
Expand Down

0 comments on commit 649d14c

Please sign in to comment.