Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
initial plugin system
  • Loading branch information
yingjiu committed May 12, 2018
1 parent bf7d29c commit f208c11
Show file tree
Hide file tree
Showing 8 changed files with 873 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

[doc](./README-EN.md) | [release](https://github.com/ICKelin/gtun/releases)
### gtun是什么
gtun是一个加速器,包含有加速器的客户端和服务端的实现,同时gtun为所有客户端虚拟出一个局域网,客户端与客户端之间通过局域网ip即可进行访问。
- gtun是一个加速器,包含有加速器的客户端和服务端的实现
- gtun支持构建虚拟局域网
- gtun支持内网穿透(version-0.0.3)

### 限制

Expand Down
128 changes: 128 additions & 0 deletions plugins/dns/config.go
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)
}
144 changes: 144 additions & 0 deletions plugins/dns/dns.go
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")
}
32 changes: 32 additions & 0 deletions plugins/dns/main.go
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()
}
Loading

0 comments on commit f208c11

Please sign in to comment.