Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pcmid committed Jan 12, 2020
0 parents commit 7548503
Show file tree
Hide file tree
Showing 27 changed files with 1,464 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/mdns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: tagged-release
on:
push:
tags: "v*"

jobs:
build:
name: Tagged Release
runs-on: ubuntu-latest
env:
GO111MODULE: on
GOOS: linux
steps:

- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v1

- name: Build
run: for GOARCH in {amd64,arm64,arm,ppc64,ppc64le}; do echo "go build for ${GOARCH}";GOARCH=${GOARCH} go build -o mdns_${GOOS}_${GOARCH} .; done

- name: Package
run: for GOARCH in {amd64,arm64,arm,ppc64,ppc64le}; do tar -zcvf mdns_${GOOS}_${GOARCH}.tar.gz mdns_${GOOS}_${GOARCH} config.sample.d mdns.service; done

- uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
files: mdns_*.tar.gz


2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
go.sum
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# mdns
4 changes: 4 additions & 0 deletions config.sample.d/cache.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Capacity": 1024,
"MTTL": 3600
}
13 changes: 13 additions & 0 deletions config.sample.d/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"Addr": ":53",
"Upstream": {
"Name": "Google DNS",
"Address": "8.8.8.8:53",
"Protocol": "tcp",
"SOCKS5Address": "127.0.0.1:1080",
"Timeout": 6
},

"PluginConfDir" : "config.sample.d/",
"Plugins" : ["log", "cache", "dispatcher", "ipset"]
}
14 changes: 14 additions & 0 deletions config.sample.d/dispatcher.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Areas": {
"CN": {
"Upstream": {
"Name": "DNSPOD DNS",
"Address": "114.114.114.114:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 6
},
"DomainFile": "config.sample.d/domain_test.txt"
}
}
}
1 change: 1 addition & 0 deletions config.sample.d/domain_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test.com
6 changes: 6 additions & 0 deletions config.sample.d/ipset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"name": "TEST",
"domain_file": "conf.d/domain_test.txt"
}
]
4 changes: 4 additions & 0 deletions config.sample.d/log.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"level": "debug",
"log_file": ""
}
32 changes: 32 additions & 0 deletions core/common/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package common

import (
"github.com/miekg/dns"
)

type Context struct {
Client dns.ResponseWriter
Err error
Upstream *DNSUpstream
Query *dns.Msg
Response *dns.Msg

IsQuery bool

returned bool
}

func (c *Context) Return() {
if c.returned == true {
return
}

_ = c.Client.WriteMsg(c.Response)
_ = c.Client.Close()
c.returned = true
}

func (c *Context) Abort() {
_ = c.Client.Close()
c.returned = true
}
9 changes: 9 additions & 0 deletions core/common/upstream.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package common

type DNSUpstream struct {
Name string
Address string
Protocol string
SOCKS5Address string
Timeout int
}
41 changes: 41 additions & 0 deletions core/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package config

import (
"encoding/json"
"github.com/pcmid/mdns/core/common"
log "github.com/sirupsen/logrus"
"io/ioutil"
"os"
)

type Config struct {
Addr string `json:"Addr"`
Upstream *common.DNSUpstream

PluginConfDir string
Plugins []string
}

func NewConfig(configFile string) *Config {
f, err := os.Open(configFile)
if err != nil {
log.Fatal("Open config file failed: ", err)
os.Exit(1)
}
defer f.Close()

b, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal("Read config file failed: ", err)
os.Exit(1)
}

j := new(Config)
err = json.Unmarshal(b, j)
if err != nil {
log.Fatal("Json syntax error: ", err)
os.Exit(1)
}

return j
}
31 changes: 31 additions & 0 deletions core/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package core

import (
"github.com/pcmid/mdns/core/config"
"github.com/pcmid/mdns/core/server"
"github.com/pcmid/mdns/plugin"
log "github.com/sirupsen/logrus"
)

func InitServer(configFilePath string) {

conf := config.NewConfig(configFilePath)

var plugins []plugin.Plugin

for _, name := range conf.Plugins {
p := plugin.Get(name)

if p == nil {
log.Errorf("unknown plugin: %s", name)
continue
}

p.Init(conf.PluginConfDir)
plugins = append(plugins, p)
}

s := server.NewServer(conf.Addr, conf.Upstream, plugins)

s.Run()
}
179 changes: 179 additions & 0 deletions core/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package server

import (
"crypto/tls"
"github.com/pcmid/mdns/core/common"
"github.com/pcmid/mdns/plugin"
"golang.org/x/net/proxy"
"net"
"os"
"strings"
"sync"
"time"

"github.com/miekg/dns"
log "github.com/sirupsen/logrus"
)

type Server struct {
addr string

upstream *common.DNSUpstream

inPlugin []plugin.Plugin
outPlugin []plugin.Plugin
}

func NewServer(addr string, upstream *common.DNSUpstream, plugins []plugin.Plugin) *Server {
s := &Server{
addr: addr,
upstream: upstream,
}

for _, p := range plugins {
if p.Where()&plugin.IN != 0 {
s.inPlugin = append(s.inPlugin, p)
}

if p.(plugin.Plugin).Where()&plugin.OUT != 0 {
s.outPlugin = append(s.outPlugin, p)
}
}

return s
}

func (s *Server) Run() {
mux := dns.NewServeMux()
mux.Handle(".", s)

wg := new(sync.WaitGroup)
wg.Add(1)

log.Info("Start mdns on " + s.addr)

for _, p := range [2]string{"tcp", "udp"} {
go func(p string) {
err := dns.ListenAndServe(s.addr, p, mux)
if err != nil {
log.Fatal("Listen "+p+" failed: ", err)
os.Exit(1)
}
}(p)
}

wg.Wait()
}

func (s *Server) ServeDNS(w dns.ResponseWriter, q *dns.Msg) {
ctx := &common.Context{
Client: w,
Upstream: s.upstream,
Query: q,
IsQuery: true,
}

if len(ctx.Query.Question) <= 0 {
log.Warnf("nil request from %s", ctx.Client.RemoteAddr())
ctx.Abort()
return
}

for _, p := range s.inPlugin {
p.HandleDns(ctx)
}

s.Exchange(ctx)
ctx.IsQuery = false

if ctx.Response == nil {
log.Errorf("nil response for %s", ctx.Query.Question[0].Name)
dns.HandleFailed(w, q)
return
}

if ctx.Err != nil {
log.Error(ctx.Err)
}

for _, p := range s.outPlugin {
p.HandleDns(ctx)
}

ctx.Return()
}

func (s *Server) Exchange(ctx *common.Context) {
if ctx.Upstream == nil {
ctx.Upstream = s.upstream
}

upstream := ctx.Upstream

var conn net.Conn
if upstream.SOCKS5Address != "" {
s, e := proxy.SOCKS5(upstream.Protocol, upstream.SOCKS5Address, nil, proxy.Direct)
if e != nil {
log.Errorf("get socks5 proxy dialer failed: %v", e)
return
}
conn, e = s.Dial(upstream.Protocol, upstream.Address)
if e != nil {
log.Errorf("dial DNS upstream with SOCKS5 proxy failed: %v", e)
return
}
} else if upstream.Protocol == "tcp-tls" {
var err error
conf := &tls.Config{
InsecureSkipVerify: false,
}
s := strings.Split(upstream.Address, "@")
if len(s) == 2 {
var servername, port string
if servername, port, err = net.SplitHostPort(s[0]); err != nil {
log.Errorf("DNS-over-TLS servername:port@serverAddress config failed: %v", err)
return
}
conf.ServerName = servername
upstream.Address = s[1] + ":" + port
}
if conn, err = tls.Dial("tcp", upstream.Address, conf); err != nil {
log.Errorf("dial DNS-over-TLS upstream failed: %v", err)
return
}
} else {
var err error
if conn, err = net.Dial(upstream.Protocol, upstream.Address); err != nil {
log.Errorf("dial DNS upstream failed: %v", err)
return
}
}

dnsTimeout := time.Duration(upstream.Timeout) * time.Second / 3

_ = conn.SetDeadline(time.Now().Add(dnsTimeout))
_ = conn.SetReadDeadline(time.Now().Add(dnsTimeout))
_ = conn.SetWriteDeadline(time.Now().Add(dnsTimeout))

dc := &dns.Conn{Conn: conn}
defer func() {
_ = dc.Close()
}()
err := dc.WriteMsg(ctx.Query)
if err != nil {
log.Errorf("%s: send question message failed: %v", upstream.Name, err)
return
}
temp, err := dc.ReadMsg()

if err != nil {
log.Errorf("%s: read record message failed: %v", upstream.Name, err)
return
}
if temp == nil {
log.Errorf("%s: Response message is nil, maybe timeout, please check your query or dns configuration", upstream.Name)
return
}
ctx.Response = temp
return
}
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/pcmid/mdns

go 1.13

require (
github.com/coreos/go-semver v0.3.0
github.com/digineo/go-ipset/v2 v2.2.1
github.com/miekg/dns v1.1.26
github.com/sirupsen/logrus v1.4.2
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
)
Loading

0 comments on commit 7548503

Please sign in to comment.