-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial plugin system
- Loading branch information
yingjiu
committed
May 12, 2018
1 parent
bf7d29c
commit f208c11
Showing
8 changed files
with
873 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
"github.com/pelletier/go-toml" | ||
) | ||
|
||
type Config struct { | ||
Upper []string `json:"upper"` // 上游dns | ||
Custom bool `json:"custom"` // 自定义模式 | ||
Cache bool `json:"cache"` // 缓存开关 | ||
Workers int `json:"worker"` // 工作线程数 | ||
BufferSize int `json:"buffer_size"` // 缓冲队列大小 | ||
Ipset bool `json:"ipset"` // ipset开关 | ||
RulesDir string `json:"rulesDir"` // 配置规则路径 | ||
ResolveFile string `json:"resolve_file"` // 上游dns配置文件,兼容dnsmasq | ||
BuildIn bool `json:"build_in_domain"` // 开启内置域名映射功能 | ||
AccessToken string `json:"access_token"` // 访问授权码 | ||
} | ||
|
||
var ( | ||
gConfig *Config | ||
) | ||
|
||
func LoadConfig(fpath string) (*Config, error) { | ||
cnt, err := ioutil.ReadFile(fpath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
cnt = removeComment(cnt) | ||
|
||
var conf = &Config{} | ||
json.Unmarshal(cnt, conf) | ||
|
||
upper, err := LoadResolveFile(conf.ResolveFile) | ||
if err == nil { | ||
conf.Upper = upper | ||
} | ||
|
||
gConfig = conf | ||
|
||
return conf, err | ||
} | ||
|
||
// 兼容dnsmasq,从指定路径加载上游dns地址 | ||
func LoadResolveFile(resolve string) ([]string, error) { | ||
file, err := os.Open(resolve) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
upper := make([]string, 0) | ||
br := bufio.NewReader(file) | ||
for { | ||
line, _, err := br.ReadLine() | ||
if err != nil { | ||
break | ||
} | ||
|
||
str := string(line) | ||
// comment | ||
if strings.HasPrefix(str, "#") { | ||
continue | ||
} | ||
|
||
if strings.HasPrefix(str, "nameserver") { | ||
sp := strings.Split(str, " ") | ||
if len(sp) != 2 { | ||
continue | ||
} | ||
ip := sp[1] | ||
upper = append(upper, ip) | ||
} | ||
} | ||
return upper, err | ||
} | ||
|
||
func removeComment(content []byte) []byte { | ||
bc := make([]byte, 0) | ||
status := 0 | ||
for _, v := range content { | ||
if v == '#' { | ||
status = 1 | ||
continue | ||
} | ||
|
||
if v == '\n' { | ||
status = 0 | ||
} | ||
|
||
if status == 1 { | ||
continue | ||
} | ||
|
||
bc = append(bc, v) | ||
} | ||
return bc | ||
} | ||
|
||
func GetConfig() *Config { | ||
return gConfig | ||
} | ||
|
||
func SetConfig(conf *Config) { | ||
gConfig = conf | ||
} | ||
|
||
func (this *Config) IsCacheOn() bool { | ||
return this.Cache | ||
} | ||
|
||
func (this *Config) IsCustomOn() bool { | ||
return this.Custom | ||
} | ||
|
||
func (this *Config) String() string { | ||
d, err := toml.Marshal(*this) | ||
if err != nil { | ||
return err.Error() | ||
} | ||
return string(d) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package dns | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"strings" | ||
|
||
"github.com/ICKelin/glog" | ||
"github.com/miekg/dns" | ||
) | ||
|
||
type DNS struct { | ||
addr string | ||
worker *Worker | ||
} | ||
|
||
func NewDNS(addr string, worker *Worker) *DNS { | ||
return &DNS{ | ||
addr: addr, | ||
worker: worker, | ||
} | ||
} | ||
|
||
func (this *DNS) String() string { | ||
return fmt.Sprintf("addr %s worker size %d", this.addr, this.worker.Size()) | ||
} | ||
|
||
func (this *DNS) Run() { | ||
laddr, err := net.ResolveUDPAddr("udp", this.addr) | ||
if err != nil { | ||
glog.ERROR(err) | ||
return | ||
} | ||
|
||
conn, err := net.ListenUDP("udp", laddr) | ||
if err != nil { | ||
glog.ERROR(err) | ||
return | ||
} | ||
|
||
glog.INFO("DNS Run", this.String()) | ||
|
||
for { | ||
data := make([]byte, 512) | ||
n, raddr, err := conn.ReadFromUDP(data) | ||
if err != nil || raddr == nil { | ||
continue | ||
} | ||
|
||
if n > 512 { | ||
glog.WARM("dns pkt too large", n) | ||
} | ||
|
||
this.worker.Notify(conn, data[:n], raddr) | ||
} | ||
} | ||
|
||
func Decode(data []byte) (*dns.Msg, error) { | ||
var dnsMsg = &dns.Msg{} | ||
if err := dnsMsg.Unpack(data); err != nil { | ||
return nil, fmt.Errorf("worker, unpack msg, err: %s", err.Error()) | ||
} | ||
|
||
return dnsMsg, nil | ||
} | ||
|
||
func GetDNSQuestions(msg *dns.Msg) string { | ||
x := []string{} | ||
for i := range msg.Question { | ||
x = append(x, msg.Question[i].Name+dns.TypeToString[msg.Question[i].Qtype]) | ||
} | ||
return strings.Join(x, ",") | ||
} | ||
|
||
func GetDNSAnswers(msg *dns.Msg) string { | ||
x := []string{} | ||
for i := range msg.Answer { | ||
x = append(x, msg.Answer[i].Header().Name+dns.TypeToString[msg.Answer[i].Header().Rrtype]) | ||
} | ||
return strings.Join(x, ",") | ||
} | ||
|
||
func String(msg *dns.Msg) string { | ||
return fmt.Sprintf("Q:%s, R:%s", GetDNSQuestions(msg), GetDNSAnswers(msg)) | ||
} | ||
|
||
func FindAnswers(msg *dns.Msg) ([]string, bool) { | ||
x := []string{} | ||
for i := range msg.Answer { | ||
if msg.Answer[i] == nil { | ||
continue | ||
} | ||
if msg.Answer[i].Header().Rrtype == dns.TypeA { | ||
if an, ok := msg.Answer[i].(*dns.A); ok { | ||
ip := an.A.To4() | ||
sip := fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) | ||
x = append(x, sip) | ||
} | ||
} | ||
if msg.Answer[i].Header().Rrtype == dns.TypeAAAA { | ||
if an, ok := msg.Answer[i].(*dns.AAAA); ok { | ||
ip16 := an.AAAA.To16() | ||
x = append(x, ip16.String()) | ||
} | ||
} | ||
} | ||
return x, len(x) > 0 | ||
} | ||
|
||
func HasRecord(msg *dns.Msg, recordType uint16) bool { | ||
for _, n := range msg.Ns { | ||
if n.Header().Rrtype == recordType { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
func HasNsRecord(msg *dns.Msg) bool { | ||
return HasRecord(msg, dns.TypeNS) | ||
} | ||
|
||
func HasARecord(msg *dns.Msg) bool { | ||
return HasRecord(msg, dns.TypeA) | ||
} | ||
|
||
func HasCNameRecord(msg *dns.Msg) bool { | ||
return HasRecord(msg, dns.TypeCNAME) | ||
} | ||
|
||
func HasAAAARecord(msg *dns.Msg) bool { | ||
return HasRecord(msg, dns.TypeAAAA) | ||
} | ||
|
||
func HasPTRRecord(msg *dns.Msg) bool { | ||
return HasRecord(msg, dns.TypePTR) | ||
} | ||
|
||
func HandleNSResponse(response *dns.Msg, server net.Conn) (*dns.Msg, error) { | ||
return nil, fmt.Errorf("unimplement ns record") | ||
} | ||
|
||
func HandleCNameResponse(response *dns.Msg, server net.Conn) (*dns.Msg, error) { | ||
return nil, fmt.Errorf("unimplements cname record") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package dns | ||
|
||
import ( | ||
"flag" | ||
|
||
_ "net/http/pprof" | ||
|
||
"github.com/ICKelin/glog" | ||
) | ||
|
||
var ( | ||
flgConfig = flag.String("conf", "./config.json", "config file") | ||
) | ||
|
||
func Run(confpath string) { | ||
conf, err := LoadConfig(confpath) | ||
if err != nil { | ||
glog.ERROR(err) | ||
return | ||
} | ||
|
||
selfDefine := NewSelfDefine(conf.RulesDir, conf.RulesDir+"/config") | ||
go selfDefine.Run() | ||
|
||
resolver := NewResolver() | ||
|
||
worker := NewWorker(conf.Workers, conf.BufferSize, selfDefine, resolver) | ||
go worker.Run() | ||
|
||
dns := NewDNS(":53", worker) | ||
go dns.Run() | ||
} |
Oops, something went wrong.