├── .gitignore ├── README.md ├── cmd └── cmd.go ├── conf └── app.ini ├── main.go ├── models ├── dns_info.go ├── init.go ├── models.go └── models_test.go ├── public └── css │ └── css.css ├── settings └── settings.go ├── templates ├── index.html └── index_m.html ├── util ├── init.go ├── proxy.go └── proxy_test.go └── web ├── init.go ├── routers └── index.go └── web.go /.gitignore: -------------------------------------------------------------------------------- 1 | models/conf 2 | util/conf 3 | .idea 4 | main 5 | data.db 6 | app.ini_bak 7 | app.ini_tmp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## xsec-dns-server 2 | 3 | xsec dns proxy server为一个DNS代理服务器,可以将DNS请求代理到后端的DNS服务器中,在代理的过程中会将dns log写入到数据库中。 4 | 5 | ### 主要特性如下: 6 | 7 | 1. 代理DNS请求并记录请求数据 8 | 1. 后端支持 sqlite、postgres、mysql和mongodb四种数据库 9 | 10 | ### 使用说明: 11 | 12 | ```shell 13 | $ ./xsec-dns-server 14 | [xorm] [info] 2017/08/15 11:01:24.497380 PING DATABASE mysql 15 | NAME: 16 | xsec dns proxy server - xsec dns proxy server 17 | 18 | USAGE: 19 | xsec-dns-server [global options] command [command options] [arguments...] 20 | 21 | VERSION: 22 | 0.1 23 | 24 | COMMANDS: 25 | serve dns proxy Server 26 | web web server 27 | help, h Shows a list of commands or help for one command 28 | 29 | GLOBAL OPTIONS: 30 | --help, -h show help 31 | --version, -v print the version 32 | 33 | ``` 34 | 35 | - serve参数表示启动一个dns代理服务器 36 | - web 参数表示启动一个简单WEB服务器,用来查看dns日志。 37 | 38 | ### 运行截图 39 | 40 | ![](https://docs.xsec.io/images/serve.png) 41 | 42 | ![](https://docs.xsec.io/images/web.png) -------------------------------------------------------------------------------- /cmd/cmd.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/urfave/cli" 5 | 6 | "xsec-dns-server/web" 7 | "xsec-dns-server/util" 8 | ) 9 | 10 | var Serve = cli.Command{ 11 | Name: "serve", 12 | Usage: "dns proxy Server", 13 | Description: "Start dns proxy server", 14 | Action: util.Run, 15 | } 16 | 17 | var RunWeb = cli.Command{ 18 | Name: "web", 19 | Usage: "web server", 20 | Description: "dns log web server", 21 | Action: web.RunWeb, 22 | } 23 | -------------------------------------------------------------------------------- /conf/app.ini: -------------------------------------------------------------------------------- 1 | [DNS_PROXY] 2 | LISTEN_HOST = 3 | LISTEN_PORT = 53 4 | DEBUG_MODE = true 5 | DNS_SERVER = 114.114.114.114:53 6 | 7 | [WEB_SERVER] 8 | HTTP_HOST = 9 | HTTP_PORT = 8088 10 | 11 | [DATA] 12 | ; DATA_TYPE value: postgres, sqlite, mysql, mongodb 13 | DATA_TYPE = mysql 14 | DATA_HOST = 127.0.0.1 15 | DATA_PORT = 3306 16 | DATA_NAME = dns_proxy 17 | USERNAME = xsec 18 | PASSWORD = www.xsec.io 19 | 20 | ; DATA_TYPE value: postgres, sqlite, mysql, mongodb 21 | ;DATA_TYPE = postgres 22 | ;DATA_HOST = 127.0.0.1 23 | ;DATA_PORT = 5432 24 | ;DATA_NAME = dns_proxy 25 | ;USERNAME = xsec 26 | ;PASSWORD = www.xsec.io 27 | ;SSL_MODE = disable 28 | 29 | ; DATA_TYPE value: postgres, sqlite, mysql, mongodb 30 | ;DATA_TYPE = mongodb 31 | ;DATA_HOST = 127.0.0.1 32 | ;DATA_PORT = 27017 33 | ;DATA_NAME = dns_proxy 34 | ;USERNAME = xsec 35 | ;PASSWORD = www.xsec.io 36 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "runtime" 6 | 7 | "xsec-dns-server/cmd" 8 | 9 | "github.com/urfave/cli" 10 | ) 11 | 12 | func main() { 13 | app := cli.NewApp() 14 | app.Name = "xsec dns proxy server" 15 | app.Usage = "xsec dns proxy server" 16 | app.Version = "0.1" 17 | app.Commands = []cli.Command{ 18 | cmd.Serve, 19 | cmd.RunWeb, 20 | } 21 | app.Run(os.Args) 22 | } 23 | 24 | func init() { 25 | runtime.GOMAXPROCS(runtime.NumCPU()) 26 | } 27 | -------------------------------------------------------------------------------- /models/dns_info.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | "gopkg.in/mgo.v2/bson" 6 | ) 7 | 8 | type DnsInfo struct { 9 | Id int64 10 | DomainName string `xorm:"Domain_name"` 11 | ClientIp string `xorm:"client_ip"` 12 | DnsRecord []string `xorm:"dns_record"` 13 | CreateAt time.Time `xorm:"created"` 14 | } 15 | 16 | type MgoDnsInfo struct { 17 | Id bson.ObjectId `bson:"_id"` 18 | DomainName string `bson:"domain_name"` 19 | ClientIp string `bson:"client_ip"` 20 | DnsRecord []string `bson:"dns_record"` 21 | CreateAt time.Time `bson:"created"` 22 | } 23 | 24 | func NewDnsInfo(domain, client string, record []string) (*DnsInfo) { 25 | return &DnsInfo{DomainName: domain, ClientIp: client, DnsRecord: record} 26 | } 27 | 28 | func (d *DnsInfo) Insert() (int64, error) { 29 | return Engine.Insert(d) 30 | } 31 | 32 | func Query() ([]DnsInfo, error) { 33 | dnsInfos := make([]DnsInfo, 0) 34 | err := Engine.Table("dns_info").Desc("id").Limit(1000, 0).Find(&dnsInfos) 35 | return dnsInfos, err 36 | } 37 | 38 | func NewMgoDnsInfo(domain, client string, record []string) (*MgoDnsInfo) { 39 | now := time.Now() 40 | return &MgoDnsInfo{DomainName: domain, ClientIp: client, DnsRecord: record, CreateAt: now, Id: bson.NewObjectId()} 41 | } 42 | 43 | func (m *MgoDnsInfo) Insert() (error) { 44 | _, err := MongodbClient.Collection("dns_info").Insert(m) 45 | return err 46 | } 47 | 48 | func MgoQuery() ([]MgoDnsInfo, error) { 49 | mgoDnsInfos := make([]MgoDnsInfo, 0) 50 | res := MongodbClient.Collection("dns_info").Find("-_id").OrderBy().Limit(1000) 51 | err := res.All(&mgoDnsInfos) 52 | return mgoDnsInfos, err 53 | } 54 | -------------------------------------------------------------------------------- /models/init.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "xsec-dns-server/settings" 5 | 6 | "github.com/go-xorm/xorm" 7 | 8 | "upper.io/db.v3" 9 | 10 | "log" 11 | ) 12 | 13 | var ( 14 | DATA_TYPE string 15 | DATA_NAME string 16 | DATA_HOST string 17 | DATA_PORT int 18 | USERNAME string 19 | PASSWORD string 20 | SSL_MODE string 21 | 22 | Engine *xorm.Engine 23 | MongodbClient db.Database 24 | ) 25 | 26 | func init() { 27 | log.SetPrefix("[xsec-dns-proxy ] ") 28 | cfg := settings.Cfg 29 | sec := cfg.Section("DATA") 30 | DATA_TYPE = sec.Key("DATA_TYPE").MustString("sqlite") 31 | DATA_NAME = sec.Key("DATA_NAME").MustString("data") 32 | DATA_HOST = sec.Key("DATA_HOST").MustString("DATA_HOST") 33 | DATA_PORT = sec.Key("DATA_PORT").MustInt(3306) 34 | USERNAME = sec.Key("USERNAME").MustString("USERNAME") 35 | PASSWORD = sec.Key("PASSWORD").MustString("PASSWORD") 36 | SSL_MODE = sec.Key("SSL_MODE").MustString("disable") 37 | 38 | NewDbEngine() 39 | 40 | switch DATA_TYPE { 41 | case "mongodb": 42 | // MongodbClient.Ping() 43 | default: 44 | Engine.Sync2(new(DnsInfo)) 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /models/models.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | 7 | "github.com/go-xorm/xorm" 8 | _ "github.com/go-sql-driver/mysql" 9 | _ "github.com/lib/pq" 10 | _ "github.com/mattn/go-sqlite3" 11 | 12 | "upper.io/db.v3/mongo" 13 | ) 14 | 15 | // init a database instance 16 | func NewDbEngine() (err error) { 17 | switch DATA_TYPE { 18 | case "sqlite": 19 | cur, _ := filepath.Abs("..") 20 | dataSourceName := fmt.Sprintf("%v/%v/%v.db", cur, DATA_NAME, DATA_NAME) 21 | Engine, err = xorm.NewEngine("sqlite3", dataSourceName) 22 | err = Engine.Ping() 23 | 24 | case "mysql": 25 | dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8", 26 | USERNAME, PASSWORD, DATA_HOST, DATA_PORT, DATA_NAME) 27 | 28 | Engine, err = xorm.NewEngine("mysql", dataSourceName) 29 | err = Engine.Ping() 30 | case "postgres": 31 | dbSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", USERNAME, PASSWORD, DATA_HOST, 32 | DATA_PORT, DATA_NAME, SSL_MODE) 33 | Engine, err = xorm.NewEngine("postgres", dbSourceName) 34 | err = Engine.Ping() 35 | 36 | case "mongodb": 37 | err = NewMongodbClient() 38 | err = MongodbClient.Ping() 39 | 40 | default: 41 | cur, _ := filepath.Abs("..") 42 | dataSourceName := fmt.Sprintf("%v/%v/%v.db", cur, DATA_NAME, DATA_NAME) 43 | Engine, err = xorm.NewEngine("sqlite3", dataSourceName) 44 | err = Engine.Ping() 45 | } 46 | 47 | return err 48 | } 49 | 50 | // return a mongodb session 51 | func NewMongodbClient() (err error) { 52 | setting := mongo.ConnectionURL{Host: fmt.Sprintf("%v:%v", DATA_HOST, DATA_PORT), Database: DATA_NAME, User: USERNAME, Password: PASSWORD} 53 | MongodbClient, err = mongo.Open(setting) 54 | return err 55 | } 56 | -------------------------------------------------------------------------------- /models/models_test.go: -------------------------------------------------------------------------------- 1 | package models_test 2 | 3 | import ( 4 | "testing" 5 | "xsec-dns-server/models" 6 | ) 7 | 8 | func TestNewDbEngine(t *testing.T) { 9 | t.Log(models.NewDbEngine()) 10 | } 11 | -------------------------------------------------------------------------------- /public/css/css.css: -------------------------------------------------------------------------------- 1 | body { 2 | /*width: 1000px;*/ 3 | /*margin: 20px auto;*/ 4 | font-family: 'trebuchet MS', 'Lucida sans', Arial; 5 | font-size: 14px; 6 | color: #444; 7 | } 8 | 9 | table { 10 | *border-collapse: collapse; /* IE7 and lower */ 11 | border-spacing: 0; 12 | width: 100%; 13 | } 14 | 15 | .bordered { 16 | border: solid #ccc 1px; 17 | -moz-border-radius: 6px; 18 | -webkit-border-radius: 6px; 19 | border-radius: 6px; 20 | -webkit-box-shadow: 0 1px 1px #ccc; 21 | -moz-box-shadow: 0 1px 1px #ccc; 22 | box-shadow: 0 1px 1px #ccc; 23 | } 24 | 25 | .bordered tr:hover { 26 | background: #fbf8e9; 27 | -o-transition: all 0.1s ease-in-out; 28 | -webkit-transition: all 0.1s ease-in-out; 29 | -moz-transition: all 0.1s ease-in-out; 30 | -ms-transition: all 0.1s ease-in-out; 31 | transition: all 0.1s ease-in-out; 32 | } 33 | 34 | .bordered td, .bordered th { 35 | border-left: 1px solid #ccc; 36 | border-top: 1px solid #ccc; 37 | padding: 10px; 38 | text-align: left; 39 | } 40 | 41 | .bordered th { 42 | background-color: #dce9f9; 43 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); 44 | background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); 45 | background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); 46 | background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); 47 | background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); 48 | background-image: linear-gradient(top, #ebf3fc, #dce9f9); 49 | -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 50 | -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 51 | box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 52 | border-top: none; 53 | text-shadow: 0 1px 0 rgba(255, 255, 255, .5); 54 | } 55 | 56 | .bordered td:first-child, .bordered th:first-child { 57 | border-left: none; 58 | } 59 | 60 | .bordered th:first-child { 61 | -moz-border-radius: 6px 0 0 0; 62 | -webkit-border-radius: 6px 0 0 0; 63 | border-radius: 6px 0 0 0; 64 | } 65 | 66 | .bordered th:last-child { 67 | -moz-border-radius: 0 6px 0 0; 68 | -webkit-border-radius: 0 6px 0 0; 69 | border-radius: 0 6px 0 0; 70 | } 71 | 72 | .bordered th:only-child { 73 | -moz-border-radius: 6px 6px 0 0; 74 | -webkit-border-radius: 6px 6px 0 0; 75 | border-radius: 6px 6px 0 0; 76 | } 77 | 78 | .bordered tr:last-child td:first-child { 79 | -moz-border-radius: 0 0 0 6px; 80 | -webkit-border-radius: 0 0 0 6px; 81 | border-radius: 0 0 0 6px; 82 | } 83 | 84 | .bordered tr:last-child td:last-child { 85 | -moz-border-radius: 0 0 6px 0; 86 | -webkit-border-radius: 0 0 6px 0; 87 | border-radius: 0 0 6px 0; 88 | } 89 | 90 | /*----------------------*/ 91 | 92 | .zebra td, .zebra th { 93 | padding: 10px; 94 | border-bottom: 1px solid #f2f2f2; 95 | } 96 | 97 | .zebra tbody tr:nth-child(even) { 98 | background: #f5f5f5; 99 | -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 100 | -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 101 | box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset; 102 | } 103 | 104 | .zebra th { 105 | text-align: left; 106 | text-shadow: 0 1px 0 rgba(255, 255, 255, .5); 107 | border-bottom: 1px solid #ccc; 108 | background-color: #eee; 109 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#eee)); 110 | background-image: -webkit-linear-gradient(top, #f5f5f5, #eee); 111 | background-image: -moz-linear-gradient(top, #f5f5f5, #eee); 112 | background-image: -ms-linear-gradient(top, #f5f5f5, #eee); 113 | background-image: -o-linear-gradient(top, #f5f5f5, #eee); 114 | background-image: linear-gradient(top, #f5f5f5, #eee); 115 | } 116 | 117 | .zebra th:first-child { 118 | -moz-border-radius: 6px 0 0 0; 119 | -webkit-border-radius: 6px 0 0 0; 120 | border-radius: 6px 0 0 0; 121 | } 122 | 123 | .zebra th:last-child { 124 | -moz-border-radius: 0 6px 0 0; 125 | -webkit-border-radius: 0 6px 0 0; 126 | border-radius: 0 6px 0 0; 127 | } 128 | 129 | .zebra th:only-child { 130 | -moz-border-radius: 6px 6px 0 0; 131 | -webkit-border-radius: 6px 6px 0 0; 132 | border-radius: 6px 6px 0 0; 133 | } 134 | 135 | .zebra tfoot td { 136 | border-bottom: 0; 137 | border-top: 1px solid #fff; 138 | background-color: #f1f1f1; 139 | } 140 | 141 | .zebra tfoot td:first-child { 142 | -moz-border-radius: 0 0 0 6px; 143 | -webkit-border-radius: 0 0 0 6px; 144 | border-radius: 0 0 0 6px; 145 | } 146 | 147 | .zebra tfoot td:last-child { 148 | -moz-border-radius: 0 0 6px 0; 149 | -webkit-border-radius: 0 0 6px 0; 150 | border-radius: 0 0 6px 0; 151 | } 152 | 153 | .zebra tfoot td:only-child { 154 | -moz-border-radius: 0 0 6px 6px; 155 | -webkit-border-radius: 0 0 6px 6px; 156 | border-radius: 0 0 6px 6px; 157 | } 158 | -------------------------------------------------------------------------------- /settings/settings.go: -------------------------------------------------------------------------------- 1 | package settings 2 | 3 | import ( 4 | "gopkg.in/ini.v1" 5 | "log" 6 | ) 7 | 8 | var ( 9 | Cfg *ini.File 10 | ) 11 | 12 | func init() { 13 | log.SetPrefix("[xsec-dns-proxy ] ") 14 | var err error 15 | source := "conf/app.ini" 16 | Cfg, err = ini.Load(source) 17 | 18 | if err != nil { 19 | log.Panicln(err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dns logs 5 | 6 | 7 | 8 |

dns logs

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{range .info }} 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | {{end}} 32 |
IDDomain NameClient IPdns_recordTime
{{ .Id}}{{ .DomainName }}{{ .ClientIp }} 25 | {{ range $k, $v := .DnsRecord }} 26 |
 {{ $v }}
27 | {{ end }} 28 |
{{ .CreateAt.Format "2006-01-02 15:04:05" }}
33 | 34 | 35 | -------------------------------------------------------------------------------- /templates/index_m.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dns logs 5 | 6 | 7 | 8 |

dns logs

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{range .info }} 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | {{end}} 32 |
IDDomain NameClient IPdns_recordTime
{{ .Id.Hex }}{{ .DomainName }}{{ .ClientIp }} 25 | {{ range $k, $v := .DnsRecord }} 26 |
 {{ $v }}
27 | {{ end }} 28 |
{{ .CreateAt.Format "2006-01-02 15:04:05" }}
33 | 34 | 35 | -------------------------------------------------------------------------------- /util/init.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "xsec-dns-server/settings" 5 | "log" 6 | ) 7 | 8 | var ( 9 | LISTEN_HOST string 10 | LISTEN_PORT int 11 | DNS_SERVER string 12 | DEBUG_MODE bool 13 | ) 14 | 15 | func init() { 16 | log.SetPrefix("[xsec-dns-proxy ] ") 17 | cfg := settings.Cfg 18 | sec := cfg.Section("DNS_PROXY") 19 | LISTEN_HOST = sec.Key("LISTEN_HOST").MustString("") 20 | LISTEN_PORT = sec.Key("LISTEN_PORT").MustInt(53) 21 | DNS_SERVER = sec.Key("DNS_SERVER").MustString("8.8.8.8:53") 22 | DEBUG_MODE = sec.Key("DEBUG_MODE").MustBool(false) 23 | } 24 | -------------------------------------------------------------------------------- /util/proxy.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "os" 8 | "syscall" 9 | "os/signal" 10 | "strings" 11 | 12 | "xsec-dns-server/models" 13 | 14 | "github.com/miekg/dns" 15 | "github.com/urfave/cli" 16 | ) 17 | 18 | func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) { 19 | doProxy(DNS_SERVER, w, r) 20 | } 21 | 22 | func doProxy(addr string, w dns.ResponseWriter, req *dns.Msg) { 23 | transport := "udp" 24 | if _, ok := w.RemoteAddr().(*net.TCPAddr); ok { 25 | transport = "tcp" 26 | } 27 | if isTransfer(req) { 28 | if transport != "tcp" { 29 | dns.HandleFailed(w, req) 30 | return 31 | } 32 | t := new(dns.Transfer) 33 | c, err := t.In(req, addr) 34 | if err != nil { 35 | dns.HandleFailed(w, req) 36 | return 37 | } 38 | if err = t.Out(w, req, c); err != nil { 39 | dns.HandleFailed(w, req) 40 | return 41 | } 42 | return 43 | } 44 | c := &dns.Client{Net: transport} 45 | resp, _, err := c.Exchange(req, addr) 46 | if err != nil { 47 | dns.HandleFailed(w, req) 48 | return 49 | } 50 | 51 | targets := req.Question 52 | target := targets[0].Name 53 | client := w.RemoteAddr().String() 54 | clientIpPort := strings.Split(client, ":") 55 | clientIp := clientIpPort[0] 56 | retReplys := resp.Answer 57 | replys := make([]string, 0) 58 | for _, t := range retReplys { 59 | replys = append(replys, t.String()) 60 | } 61 | 62 | if DEBUG_MODE { 63 | log.Printf("DB type: %v, Target:%v, Client: %v, Reply: %v\n", models.DATA_TYPE, target, clientIp, strings.Join(replys, ",")) 64 | } 65 | 66 | switch models.DATA_TYPE { 67 | case "mongodb": 68 | dnsInfo := models.NewMgoDnsInfo(target, client, replys) 69 | go dnsInfo.Insert() 70 | default: 71 | dnsInfo := models.NewDnsInfo(target, clientIp, replys) 72 | go dnsInfo.Insert() 73 | } 74 | 75 | w.WriteMsg(resp) 76 | } 77 | 78 | func isTransfer(req *dns.Msg) bool { 79 | for _, q := range req.Question { 80 | switch q.Qtype { 81 | case dns.TypeIXFR, dns.TypeAXFR: 82 | return true 83 | } 84 | } 85 | return false 86 | } 87 | 88 | func Run(ctx *cli.Context) (err error) { 89 | // attach request handler func 90 | dns.HandleFunc(".", handleDnsRequest) 91 | 92 | // start server 93 | server := LISTEN_HOST 94 | port := LISTEN_PORT 95 | 96 | tcpServer := &dns.Server{Addr: fmt.Sprintf("%v:%v", server, port), Net: "tcp"} 97 | udpServer := &dns.Server{Addr: fmt.Sprintf("%v:%v", server, port), Net: "udp"} 98 | 99 | log.Printf("Starting at udp://%v:%v\n", server, port) 100 | go func() { 101 | if err := udpServer.ListenAndServe(); err != nil { 102 | log.Fatal(err) 103 | } 104 | 105 | }() 106 | 107 | log.Printf("Starting at tcp://%v:%v\n", server, port) 108 | go func() { 109 | if err := tcpServer.ListenAndServe(); err != nil { 110 | log.Fatal(err) 111 | } 112 | 113 | }() 114 | 115 | // Wait for SIGINT or SIGTERM 116 | sig := make(chan os.Signal, 1) 117 | signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) 118 | <-sig 119 | 120 | udpServer.Shutdown() 121 | tcpServer.Shutdown() 122 | return err 123 | } 124 | -------------------------------------------------------------------------------- /util/proxy_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "xsec-dns-server/util" 5 | "testing" 6 | ) 7 | 8 | func TestRun(t *testing.T) { 9 | t.Log(util.Run()) 10 | } 11 | -------------------------------------------------------------------------------- /web/init.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "xsec-dns-server/settings" 5 | ) 6 | 7 | var ( 8 | HTTP_HOST string 9 | HTTP_PORT int 10 | ) 11 | 12 | func init() { 13 | cfg := settings.Cfg 14 | sec := cfg.Section("WEB_SERVER") 15 | HTTP_HOST = sec.Key("HTTP_HOST").MustString("127.0.0.1") 16 | HTTP_PORT = sec.Key("HTTP_PORT").MustInt(8088) 17 | } 18 | -------------------------------------------------------------------------------- /web/routers/index.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | "gopkg.in/macaron.v1" 5 | 6 | "xsec-dns-server/models" 7 | ) 8 | 9 | func Index(ctx *macaron.Context) { 10 | switch models.DATA_TYPE { 11 | case "mongodb": 12 | info, _ := models.MgoQuery() 13 | ctx.Data["info"] = info 14 | ctx.HTML(200, "index_m") 15 | default: 16 | info, _ := models.Query() 17 | ctx.Data["info"] = info 18 | ctx.HTML(200, "index") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /web/web.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/go-macaron/cache" 9 | "github.com/go-macaron/csrf" 10 | "github.com/go-macaron/session" 11 | "github.com/urfave/cli" 12 | "gopkg.in/macaron.v1" 13 | 14 | "xsec-dns-server/web/routers" 15 | ) 16 | 17 | func RunWeb(ctx *cli.Context) (err error) { 18 | m := macaron.Classic() 19 | m.Use(macaron.Renderer()) 20 | m.Use(session.Sessioner()) 21 | m.Use(csrf.Csrfer()) 22 | m.Use(cache.Cacher()) 23 | 24 | m.Get("/", routers.Index) 25 | m.Get("/admin/index/", routers.Index) 26 | 27 | log.Printf("run server on %v\n", fmt.Sprintf("%v:%v", HTTP_HOST, HTTP_PORT)) 28 | err = http.ListenAndServe(fmt.Sprintf("%v:%v", HTTP_HOST, HTTP_PORT), m) 29 | 30 | return err 31 | } 32 | --------------------------------------------------------------------------------