Fix #2, add dhcp dynamic setting upstream dns, ipv4 only

This commit is contained in:
wweir
2019-02-02 06:21:51 +08:00
parent ae525f9b40
commit b6df69358a
7 changed files with 132 additions and 8 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ If you wanna uninstall sower, change `install` into `uninstall` and rerun the co
### Docker deploy
The auto build docker images are [wweir/sower](https://hub.docker.com/r/wweir/sower).
It is very simple to use it on the server side. Map the port and run it directly.
It is very simple to use it on the server side. Export the port(5533) and run it directly.
But the client is more troublesome and needs some understanding of the working mechanism of the sower.
+2 -1
View File
@@ -4,7 +4,7 @@ password="12345678"
server_port="5533"
# server_addr="remote-server:5533" # replce it to remote server
http_proxy=":8080" # eg: 192.168.0.2:8080
dns_server="223.5.5.5" # Alibaba public dns
dns_server="" # Keep empty for dynamic setting from net env
client_ip="127.0.0.1" # listen the IP, dns target is the IP
# clear_dns_cache="killall -HUP mDNSResponder"
blocklist=[
@@ -22,6 +22,7 @@ blocklist=[
"**.twimg.com",
"**.blogspot.com", # blogspot
"**.wikipedia.org", # wikipeida
"*.cloudfront.net",
]
whitelist=[
"iamp.*.*.*",
+85
View File
@@ -0,0 +1,85 @@
package dns
import (
"math/rand"
"net"
"github.com/golang/glog"
"github.com/wweir/netboot/dhcp4"
)
func GetDefaultDNSServer() string {
xid := make([]byte, 4)
rand.Read(xid)
pack := &dhcp4.Packet{
Type: dhcp4.MsgDiscover,
TransactionID: xid,
Broadcast: true,
}
options := map[dhcp4.Option][]byte{
dhcp4.OptRequestedOptions: []byte{byte(dhcp4.OptDNSServers)},
}
ifaces := mustGetInterfaces()
for _, iface := range ifaces {
conn, err := dhcp4.NewConn(iface.IP.String() + ":68")
if err != nil {
glog.Errorln(err)
continue
}
defer conn.Close()
pack.HardwareAddr = iface.Interface.HardwareAddr
options[dhcp4.OptClientIdentifier] = iface.Interface.HardwareAddr
pack.Options = dhcp4.Options(options)
if err := conn.SendDHCP(pack, iface.Interface); err != nil {
glog.Errorln(err)
continue
}
pack, _, err = conn.RecvDHCP()
if err != nil {
glog.Errorln(err)
continue
}
ip, err := pack.Options.IP(dhcp4.OptDNSServers)
if err != nil {
glog.Errorln(err)
continue
}
return ip.String()
}
return ""
}
type netIface struct {
*net.Interface
net.Addr
net.IP
}
func mustGetInterfaces() []*netIface {
ifaces, err := net.Interfaces()
if err != nil {
glog.Fatalln(err)
}
v4Iface := make([]*netIface, 0, len(ifaces))
for i := range ifaces {
if len(ifaces[i].HardwareAddr) == 0 {
continue
}
addrs, _ := ifaces[i].Addrs()
for _, addr := range addrs {
if ip := addr.(*net.IPNet).IP.To4(); ip != nil {
v4Iface = append(v4Iface, &netIface{&ifaces[i], addr, ip})
break
}
}
}
return v4Iface
}
+21
View File
@@ -0,0 +1,21 @@
package dns
import "testing"
func TestGetDefaultDNSServer(t *testing.T) {
t.Skip("for net env")
tests := []struct {
name string
want string
}{{
"",
"192.168.1.1",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetDefaultDNSServer(); got != tt.want {
t.Errorf("GetDefaultDNSServer() = %v, want %v", got, tt.want)
}
})
}
}
+20 -6
View File
@@ -18,7 +18,9 @@ func StartDNS(dnsServer, listenIP string) {
ip := net.ParseIP(listenIP)
suggest := &intelliSuggest{listenIP, 2 * time.Second, []string{"80", "443"}}
mem.DefaultCache = mem.New(time.Hour)
dnsServer = net.JoinHostPort(dnsServer, "53")
if dnsServer != "" {
dnsServer = net.JoinHostPort(dnsServer, "53")
}
dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
// *Msg r has an TSIG record and it was validated
@@ -37,15 +39,15 @@ func StartDNS(dnsServer, listenIP string) {
domain = domain[:idx]
}
matchAndServe(w, r, domain, listenIP, dnsServer, ip, suggest)
matchAndServe(w, r, domain, listenIP, &dnsServer, ip, suggest)
})
server := &dns.Server{Addr: net.JoinHostPort(listenIP, "53"), Net: "udp"}
glog.Fatalln(server.ListenAndServe())
}
func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP,
dnsServer string, ipNet net.IP, suggest *intelliSuggest) {
func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP string,
dnsServer *string, ipNet net.IP, suggest *intelliSuggest) {
inWriteList := whiteList.Match(domain)
@@ -59,7 +61,19 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP,
go mem.Remember(suggest, domain)
}
msg, err := dns.Exchange(r, dnsServer)
if *dnsServer == "" {
host := GetDefaultDNSServer()
if host == "" {
return
}
*dnsServer = net.JoinHostPort(host, "53")
glog.Infoln("set dns server to", host)
}
msg, err := dns.Exchange(r, *dnsServer)
if err != nil {
*dnsServer = ""
}
if msg == nil { // expose any response except nil
glog.V(1).Infof("get dns of %s fail: %s", domain, err)
return
@@ -84,7 +98,7 @@ func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error)
for _, port := range i.ports {
// give local dial a hand, make it not so easy to be added into suggestions
<-util.HTTPPing(addr+port, addr, i.timeout/5)
<-util.HTTPPing(addr+port, addr, i.timeout/10)
localCh := util.HTTPPing(addr+port, addr, i.timeout)
remoteCh := util.HTTPPing(i.listenIP+port, addr, i.timeout)
+1
View File
@@ -19,6 +19,7 @@ require (
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f // indirect
github.com/wweir/fsnotify v1.4.8
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296
github.com/wweir/netboot v0.0.2
github.com/xtaci/kcp-go v5.0.7+incompatible
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
+2
View File
@@ -34,6 +34,8 @@ github.com/wweir/fsnotify v1.4.8 h1:zxOoqwE5p91F3rmcYLQheoSeTlIVqwi2b5T7UlpElWE=
github.com/wweir/fsnotify v1.4.8/go.mod h1:4GuxIc23DXfJI1/LhBXG5eE/wJ4CzL+kk5M7woxVprc=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296 h1:/HkUfg+ZMx/tNdnyJdVlhyv+xO3A7ZlpfL9nFLWLYcc=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296/go.mod h1:k7rjBGWoJ+JKwvfe8juAX0zgybjo/Yo3JGkca5f/06s=
github.com/wweir/netboot v0.0.2 h1:DFuNd97kxzgblExEKn4Nqf1du0m9qUnaTQ70rFgIjLU=
github.com/wweir/netboot v0.0.2/go.mod h1:p/WOnPHdqwgAI6YLEfdmwjwutbc/zDZ7EojAHlXLi4s=
github.com/xtaci/kcp-go v5.0.7+incompatible h1:zs9tc8XRID0m+aetu3qPWZFyRt2UIMqbXIBgw+vcnlE=
github.com/xtaci/kcp-go v5.0.7+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE=