mirror of
https://github.com/MarekWojt/gertdns.git
synced 2025-12-15 12:59:53 +01:00
Compare commits
20 Commits
942c4d30e4
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| bd377c7716 | |||
| 7826aad522 | |||
| a6e305ca5a | |||
| accedccf6c | |||
| 50333de139 | |||
| 285ea8438e | |||
| 7bf92a6241 | |||
| 250cd56b19 | |||
| 6e2d00bd6c | |||
| 74aa218cf0 | |||
| 1e3c9b806d | |||
| 621ec4b039 | |||
| d04b937750 | |||
| 378f094ce8 | |||
| 91709e65bd | |||
| 0e5a3d7361 | |||
| 80c2a5717b | |||
| b8313388b5 | |||
|
|
077de80f64 | ||
|
|
70b1b8c826 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@ gertdns
|
||||
gertdns.exe
|
||||
conf.toml
|
||||
auth.toml
|
||||
*.v4.csv
|
||||
*.v6.csv
|
||||
|
||||
31
README.md
31
README.md
@@ -8,11 +8,11 @@ go run main.go
|
||||
|
||||
Bullding:
|
||||
```sh
|
||||
go build main.go
|
||||
go build
|
||||
```
|
||||
|
||||
## Config
|
||||
`conf.toml` by default
|
||||
Default `conf.toml`
|
||||
```toml
|
||||
[DNS]
|
||||
Port = 5353 # DNS server port
|
||||
@@ -27,7 +27,7 @@ SocketFileMode = 420 # File mode for HTTP unix socket in decimal (420 =
|
||||
```
|
||||
|
||||
## Users
|
||||
`auth.toml` by default
|
||||
Default `auth.toml`
|
||||
```toml
|
||||
[someusername] # user name of the user
|
||||
Password = '1234' # password of the user
|
||||
@@ -53,3 +53,28 @@ Default: `conf.toml`
|
||||
Will define what file should be used to define users that can log in.
|
||||
Type: `string`
|
||||
Default: `auth.toml`
|
||||
|
||||
### --data-path
|
||||
Will define where stored data is put (i.e. IP addresses for subdomains). All records will be saved here every second if they have been changed and when the application gets shut down.
|
||||
Type: `string`
|
||||
Default: `.`
|
||||
|
||||
## Routes
|
||||
### `/`
|
||||
If in debug mode, will output all registered records, otherwise prints `"Working"`.
|
||||
|
||||
### `/update/{domain}/{type}`
|
||||
Updates a given record.
|
||||
#### URL parts
|
||||
`domain` (`string`): defines the subdomain that is to be modified
|
||||
`type` (`"v4"` | `"v6"`): specifies whether an IPv4 or IPv6 record is to be changed.
|
||||
#### query parameters
|
||||
`ipv4` (`string`) (only if `type` is `"v4"`): specifies the IPv4 address to be applied.
|
||||
`ipv6` (`string`) (only if `type` is `"v6"`): specifies the IPv6 address to be applied.
|
||||
`user` (`string`): username as specified in _auth file_.
|
||||
`password` (`string`): password as specified in _auth file_.
|
||||
|
||||
#### examples
|
||||
/update/**example.example**/**v4**?ipv4=**127.0.0.1**&user=**username**&password=**password**
|
||||
|
||||
/update/**example.example**/**v6**?ipv6=**::1**&user=**username**&password=**password**
|
||||
|
||||
16
auth/auth.go
16
auth/auth.go
@@ -1,8 +1,9 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"log"
|
||||
"errors"
|
||||
|
||||
"github.com/MarekWojt/gertdns/util"
|
||||
"github.com/raja/argon2pw"
|
||||
)
|
||||
|
||||
@@ -23,7 +24,7 @@ type user struct {
|
||||
domains map[string]string
|
||||
}
|
||||
|
||||
var parsedUsers map[string]user = map[string]user{}
|
||||
var parsedUsers map[string]user = make(map[string]user)
|
||||
|
||||
func (user user) Authenticate(password string) (bool, error) {
|
||||
return argon2pw.CompareHashWithPassword(user.password, password)
|
||||
@@ -40,9 +41,10 @@ func (selfUser *userRaw) Tidy() (user, error) {
|
||||
}
|
||||
|
||||
// Create a map => faster access times
|
||||
parsedDomains := map[string]string{}
|
||||
parsedDomains := make(map[string]string)
|
||||
for _, domain := range selfUser.Domains {
|
||||
parsedDomains[domain] = domain
|
||||
parsedDomain := util.ParseDomain(domain)
|
||||
parsedDomains[parsedDomain] = parsedDomain
|
||||
}
|
||||
|
||||
parsedUser := user{
|
||||
@@ -56,11 +58,11 @@ func (selfUser *userRaw) Tidy() (user, error) {
|
||||
func IsPasswordAuthenticated(request PasswordAuthenticationRequest) (bool, error) {
|
||||
currentUser, found := parsedUsers[request.User]
|
||||
if !found {
|
||||
return false, nil
|
||||
return false, errors.New("user does not exist")
|
||||
}
|
||||
|
||||
if _, ok := currentUser.domains[request.Domain]; !ok {
|
||||
return false, nil
|
||||
return false, errors.New("user does not have access to this domain")
|
||||
}
|
||||
|
||||
return currentUser.Authenticate(request.Password)
|
||||
@@ -73,8 +75,6 @@ func Init(authFilePath string) error {
|
||||
}
|
||||
|
||||
for name, user := range users {
|
||||
log.Printf("%s\n", name)
|
||||
log.Printf("%+v\n", user)
|
||||
parsedUser, err := user.Tidy()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -14,7 +14,7 @@ func loadAuthFile(authFilePath string) (map[string]*userRaw, error) {
|
||||
if err != nil {
|
||||
color.Errorln(err.Error())
|
||||
color.Warnln("Creating new authentication file")
|
||||
return writeAuthFile(authFilePath, map[string]*userRaw{})
|
||||
return writeAuthFile(authFilePath, make(map[string]*userRaw))
|
||||
}
|
||||
|
||||
var users map[string]*userRaw
|
||||
|
||||
265
dns/dns.go
265
dns/dns.go
@@ -1,79 +1,142 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/MarekWojt/gertdns/config"
|
||||
"github.com/MarekWojt/gertdns/util"
|
||||
"github.com/gookit/color"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
var domains []*domain = make([]*domain, 0)
|
||||
var saveTicker *time.Ticker = time.NewTicker(time.Second)
|
||||
var saving sync.Mutex = sync.Mutex{}
|
||||
var currentDataPath string
|
||||
|
||||
const (
|
||||
IPV4_FILE = "v4.csv"
|
||||
IPV6_FILE = "v6.csv"
|
||||
)
|
||||
|
||||
type domain struct {
|
||||
Root string
|
||||
Mutv4 sync.RWMutex
|
||||
Mutv6 sync.RWMutex
|
||||
Ipv4 map[string]string
|
||||
Ipv6 map[string]string
|
||||
Root string
|
||||
Mutv4 sync.RWMutex
|
||||
Mutv6 sync.RWMutex
|
||||
Mutv4Changed sync.RWMutex
|
||||
Mutv6Changed sync.RWMutex
|
||||
Ipv4 map[string]string
|
||||
Ipv4Changed bool
|
||||
Ipv6 map[string]string
|
||||
Ipv6Changed bool
|
||||
}
|
||||
|
||||
var domains = []*domain{}
|
||||
func (currentDomain *domain) IsV4Changed() bool {
|
||||
currentDomain.Mutv4Changed.RLock()
|
||||
result := currentDomain.Ipv4Changed
|
||||
currentDomain.Mutv4Changed.RUnlock()
|
||||
|
||||
func parseQuery(m *dns.Msg, currentDomain *domain) {
|
||||
for _, q := range m.Question {
|
||||
switch q.Qtype {
|
||||
case dns.TypeA:
|
||||
log.Printf("Query for A record of %s\n", q.Name)
|
||||
currentDomain.Mutv4.RLock()
|
||||
ip := currentDomain.Ipv4[q.Name]
|
||||
currentDomain.Mutv4.RUnlock()
|
||||
if ip != "" {
|
||||
rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, ip))
|
||||
if err == nil {
|
||||
m.Answer = append(m.Answer, rr)
|
||||
}
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
log.Printf("Query for AAAA record of %s\n", q.Name)
|
||||
currentDomain.Mutv6.RLock()
|
||||
ip := currentDomain.Ipv6[q.Name]
|
||||
currentDomain.Mutv6.RUnlock()
|
||||
if ip != "" {
|
||||
rr, err := dns.NewRR(fmt.Sprintf("%s AAAA %s", q.Name, ip))
|
||||
if err == nil {
|
||||
m.Answer = append(m.Answer, rr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (currentDomain *domain) IsV6Changed() bool {
|
||||
currentDomain.Mutv6Changed.RLock()
|
||||
result := currentDomain.Ipv6Changed
|
||||
currentDomain.Mutv6Changed.RUnlock()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (currentDomain *domain) MarkV6Changed(changed bool) {
|
||||
currentDomain.Mutv6Changed.Lock()
|
||||
currentDomain.Ipv6Changed = changed
|
||||
currentDomain.Mutv6Changed.Unlock()
|
||||
}
|
||||
|
||||
func (currentDomain *domain) MarkV4Changed(changed bool) {
|
||||
currentDomain.Mutv4Changed.Lock()
|
||||
currentDomain.Ipv4Changed = changed
|
||||
currentDomain.Mutv4Changed.Unlock()
|
||||
}
|
||||
|
||||
func (currentDomain *domain) SetV4(domain string, ipv4 string) {
|
||||
currentDomain.Mutv4.Lock()
|
||||
currentDomain.Ipv4[domain] = ipv4
|
||||
currentDomain.Mutv4.Unlock()
|
||||
}
|
||||
|
||||
func (currentDomain *domain) SetV6(domain string, ipv6 string) {
|
||||
currentDomain.Mutv6.Lock()
|
||||
currentDomain.Ipv6[domain] = ipv6
|
||||
currentDomain.Mutv6.Unlock()
|
||||
}
|
||||
|
||||
func loadFile(ty string, currentDomain *domain) {
|
||||
if ty != IPV4_FILE && ty != IPV6_FILE {
|
||||
panic("type passed to loadFile must be either IPV4_FILE or IPV6_FILE")
|
||||
}
|
||||
}
|
||||
|
||||
func handleDnsRequest(currentDomain *domain) func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
m.Compress = false
|
||||
filePath := path.Join(currentDataPath, currentDomain.Root+ty)
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
color.Warnf("Could not load file for domain %s: %s\n", currentDomain.Root, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
switch r.Opcode {
|
||||
case dns.OpcodeQuery:
|
||||
parseQuery(m, currentDomain)
|
||||
log.Printf("Reading file: %s", filePath)
|
||||
scanner := bufio.NewScanner(f)
|
||||
|
||||
lineCounter := 0
|
||||
for scanner.Scan() {
|
||||
lineCounter++
|
||||
currentLine := scanner.Text()
|
||||
cols := strings.Split(currentLine, "\t")
|
||||
if len(cols) < 2 {
|
||||
color.Warnf("Error reading line %d of ipv4 addresses for domain %s: too few columns\n", lineCounter, currentDomain.Root)
|
||||
continue
|
||||
}
|
||||
|
||||
w.WriteMsg(m)
|
||||
if ty == IPV4_FILE {
|
||||
currentDomain.Ipv4[cols[0]] = cols[1]
|
||||
} else if ty == IPV6_FILE {
|
||||
currentDomain.Ipv6[cols[0]] = cols[1]
|
||||
}
|
||||
}
|
||||
color.Infof("Read file: %s\n", filePath)
|
||||
}
|
||||
|
||||
func Init() {
|
||||
func Init(dataPath string) {
|
||||
currentDataPath = dataPath
|
||||
for _, currentDomain := range config.Config.DNS.Domains {
|
||||
currentDomain = util.ParseDomain(currentDomain)
|
||||
log.Printf("Added domain root: %s\n", currentDomain)
|
||||
domains = append(domains, &domain{
|
||||
|
||||
domainObj := &domain{
|
||||
Root: currentDomain,
|
||||
Ipv4: make(map[string]string),
|
||||
Ipv6: make(map[string]string),
|
||||
})
|
||||
}
|
||||
domains = append(domains, domainObj)
|
||||
loadFile(IPV4_FILE, domainObj)
|
||||
loadFile(IPV6_FILE, domainObj)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
<-saveTicker.C
|
||||
Save()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func Run() (*dns.Server, error) {
|
||||
@@ -98,9 +161,12 @@ func UpdateIpv6(domain string, ipv6 string) error {
|
||||
for _, currentDomain := range domains {
|
||||
if dns.IsSubDomain(currentDomain.Root, domain) {
|
||||
log.Printf("Updating domain %s AAAA %s\n", domain, ipv6)
|
||||
currentDomain.Mutv6.Lock()
|
||||
currentDomain.Ipv6[domain] = ipv6
|
||||
currentDomain.Mutv6.Unlock()
|
||||
|
||||
if !currentDomain.IsV6Changed() {
|
||||
currentDomain.MarkV6Changed(true)
|
||||
}
|
||||
|
||||
currentDomain.SetV6(domain, ipv6)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -110,11 +176,15 @@ func UpdateIpv6(domain string, ipv6 string) error {
|
||||
|
||||
func UpdateIpv4(domain string, ipv4 string) (err error) {
|
||||
for _, currentDomain := range domains {
|
||||
log.Printf("%s sub of %s ?\n", domain, currentDomain.Root)
|
||||
if dns.IsSubDomain(currentDomain.Root, domain) {
|
||||
log.Printf("Updating domain %s A %s\n", domain, ipv4)
|
||||
currentDomain.Mutv4.Lock()
|
||||
currentDomain.Ipv4[domain] = ipv4
|
||||
currentDomain.Mutv4.Unlock()
|
||||
|
||||
if !currentDomain.IsV4Changed() {
|
||||
currentDomain.MarkV4Changed(true)
|
||||
}
|
||||
|
||||
currentDomain.SetV4(domain, ipv4)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -125,3 +195,96 @@ func UpdateIpv4(domain string, ipv4 string) (err error) {
|
||||
func Get() []*domain {
|
||||
return domains
|
||||
}
|
||||
|
||||
func parseQuery(m *dns.Msg, currentDomain *domain) {
|
||||
for _, q := range m.Question {
|
||||
switch q.Qtype {
|
||||
case dns.TypeA:
|
||||
currentDomain.Mutv4.RLock()
|
||||
ip := currentDomain.Ipv4[q.Name]
|
||||
currentDomain.Mutv4.RUnlock()
|
||||
if ip != "" {
|
||||
rr, err := dns.NewRR(fmt.Sprintf(q.Name + " 300 IN A " + ip))
|
||||
if err == nil {
|
||||
m.Answer = append(m.Answer, rr)
|
||||
}
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
currentDomain.Mutv6.RLock()
|
||||
ip := currentDomain.Ipv6[q.Name]
|
||||
currentDomain.Mutv6.RUnlock()
|
||||
if ip != "" {
|
||||
rr, err := dns.NewRR(fmt.Sprintf(q.Name + " 300 IN AAAA " + ip))
|
||||
if err == nil {
|
||||
m.Answer = append(m.Answer, rr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleDnsRequest(currentDomain *domain) func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
m.Compress = false
|
||||
|
||||
switch r.Opcode {
|
||||
case dns.OpcodeQuery:
|
||||
parseQuery(m, currentDomain)
|
||||
}
|
||||
|
||||
w.WriteMsg(m)
|
||||
}
|
||||
}
|
||||
|
||||
func Save() (errs []error) {
|
||||
saving.Lock()
|
||||
for _, domain := range domains {
|
||||
if domain.IsV4Changed() {
|
||||
ipv4Data := ""
|
||||
domain.Mutv4.RLock()
|
||||
for key, val := range domain.Ipv4 {
|
||||
ipv4Data += key + "\t" + val + "\n"
|
||||
}
|
||||
domain.Mutv4.RUnlock()
|
||||
err := os.WriteFile(path.Join(currentDataPath, domain.Root+IPV4_FILE), []byte(ipv4Data), 0644)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
color.Errorf("Failed to save ipv4 data for domain %s: %s\n", domain.Root, err)
|
||||
} else {
|
||||
// did successfully save, so mark as saved
|
||||
domain.MarkV4Changed(false)
|
||||
}
|
||||
}
|
||||
|
||||
if domain.IsV6Changed() {
|
||||
ipv6Data := ""
|
||||
domain.Mutv6.RLock()
|
||||
for key, val := range domain.Ipv6 {
|
||||
ipv6Data += key + "\t" + val + "\n"
|
||||
}
|
||||
domain.Mutv6.RUnlock()
|
||||
err := os.WriteFile(path.Join(currentDataPath, domain.Root+IPV6_FILE), []byte(ipv6Data), 0644)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
color.Errorf("Failed to save ipv6 data for domain %s: %s\n", domain.Root, err)
|
||||
} else {
|
||||
// did successfully save, so mark as saved
|
||||
domain.MarkV6Changed(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
saving.Unlock()
|
||||
|
||||
errLen := len(errs)
|
||||
if errLen > 0 {
|
||||
color.Errorf("%d errors occurred while trying to save\n", errLen)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Shutdown() {
|
||||
saveTicker.Stop()
|
||||
Save()
|
||||
}
|
||||
|
||||
25
go.mod
25
go.mod
@@ -3,21 +3,24 @@ module github.com/MarekWojt/gertdns
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/fasthttp/router v1.4.4
|
||||
github.com/gookit/color v1.4.2
|
||||
github.com/miekg/dns v1.1.43
|
||||
github.com/pelletier/go-toml/v2 v2.0.0-beta.3
|
||||
github.com/fasthttp/router v1.4.14
|
||||
github.com/gookit/color v1.5.2
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/pelletier/go-toml/v2 v2.0.6
|
||||
github.com/raja/argon2pw v1.0.1
|
||||
github.com/valyala/fasthttp v1.31.0
|
||||
github.com/valyala/fasthttp v1.43.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.2 // indirect
|
||||
github.com/klauspost/compress v1.13.4 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/klauspost/compress v1.15.9 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
)
|
||||
|
||||
90
go.sum
90
go.sum
@@ -1,54 +1,82 @@
|
||||
github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fasthttp/router v1.4.4 h1:Z025tHFTjDp6T6QMBjloyGL6KV5wtakW365K/7KiE1c=
|
||||
github.com/fasthttp/router v1.4.4/go.mod h1:TiyF2kc+mogKcTxqkhUbiXpwklouv5dN58A0ZUo8J6s=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fasthttp/router v1.4.14 h1:+W65VCKgyI4BZszhDiCRfONoFieePZIoQ7D8vGhiuzM=
|
||||
github.com/fasthttp/router v1.4.14/go.mod h1:+svLaOvqF9Lc0yjX9aHAD4NUMf+mggLPOT4UMdS6fjM=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0-beta.3 h1:PNCTU4naEJ8mKal97P3A2qDU74QRQGlv4FXiL1XDqi4=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0-beta.3/go.mod h1:aNseLYu/uKskg0zpr/kbr2z8yGuWtotWf/0BpGIAL2Y=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/raja/argon2pw v1.0.1 h1:RIUM12+uQdj5/cWQLlEmZDD8xj5kQN1X9kTK0xfXjGQ=
|
||||
github.com/raja/argon2pw v1.0.1/go.mod h1:idX/fPqwjX31YMTF2iIpEpNApV2YbQhSFr4iIhJaqp4=
|
||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4 h1:ocK/D6lCgLji37Z2so4xhMl46se1ntReQQCUIU4BWI8=
|
||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
|
||||
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
|
||||
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 h1:t0lM6y/M5IiUZyvbBTcngso8SZEZICH7is9B6g/obVU=
|
||||
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE=
|
||||
github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/fasthttp v1.42.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
|
||||
github.com/valyala/fasthttp v1.43.0 h1:Gy4sb32C98fbzVWZlTM1oTMdLWGyvxR03VhM6cBIU4g=
|
||||
github.com/valyala/fasthttp v1.43.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo=
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
22
main.go
22
main.go
@@ -3,6 +3,9 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/MarekWojt/gertdns/auth"
|
||||
"github.com/MarekWojt/gertdns/config"
|
||||
@@ -12,8 +15,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
configFile = flag.String("config-file", "conf.toml", "Path to configuration file")
|
||||
authFile = flag.String("auth-file", "auth.toml", "Path to authentication file")
|
||||
configFile = flag.String("config-file", "conf.toml", "Path to configuration file")
|
||||
authFile = flag.String("auth-file", "auth.toml", "Path to authentication file")
|
||||
dataPath = flag.String("data-path", ".", "Where to save data")
|
||||
enableDebugMode = flag.Bool("enable-debug-mode", false, "Enables debug mode, will output a list of all registered records on the index page of the HTTP server")
|
||||
)
|
||||
|
||||
type dnsResult struct {
|
||||
@@ -29,8 +34,8 @@ func main() {
|
||||
log.Fatalf("Failed to load configuration: %s\n ", err.Error())
|
||||
}
|
||||
|
||||
dns.Init()
|
||||
web.Init()
|
||||
dns.Init(*dataPath)
|
||||
web.Init(*enableDebugMode)
|
||||
err = auth.Init(*authFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize authentication module: %s\n", err.Error())
|
||||
@@ -68,8 +73,17 @@ func main() {
|
||||
webChan <- err
|
||||
}()
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
dns.Shutdown()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
currentDnsResult := <-dnsChan
|
||||
defer currentDnsResult.server.Shutdown()
|
||||
defer dns.Shutdown()
|
||||
<-webChan
|
||||
<-webChan
|
||||
}
|
||||
|
||||
11
util/util.go
Normal file
11
util/util.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package util
|
||||
|
||||
import "strings"
|
||||
|
||||
func ParseDomain(domain string) string {
|
||||
if !strings.HasSuffix(domain, ".") {
|
||||
return domain + "."
|
||||
}
|
||||
|
||||
return domain
|
||||
}
|
||||
285
web/web.go
285
web/web.go
@@ -1,7 +1,6 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
@@ -9,133 +8,27 @@ import (
|
||||
"github.com/MarekWojt/gertdns/auth"
|
||||
"github.com/MarekWojt/gertdns/config"
|
||||
"github.com/MarekWojt/gertdns/dns"
|
||||
"github.com/MarekWojt/gertdns/util"
|
||||
"github.com/fasthttp/router"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
var enableDebugMode *bool = flag.Bool("enable-debug-mode", false, "Enables debug mode, will output a list of ")
|
||||
var (
|
||||
enableDebugMode bool
|
||||
r *router.Router
|
||||
ipv4Param = []byte("ipv4")
|
||||
ipv6Param = []byte("ipv6")
|
||||
userParam = []byte("user")
|
||||
passwordParam = []byte("password")
|
||||
)
|
||||
|
||||
func index(ctx *fasthttp.RequestCtx) {
|
||||
if !*enableDebugMode {
|
||||
ctx.WriteString("Working")
|
||||
} else {
|
||||
domains := dns.Get()
|
||||
ctx.SetContentType("text/html")
|
||||
ctx.WriteString("<!DOCTYPE html><html><head><meta charset='utf-8'><title>gertdns</title></head><body><table><tr><th>Type</th><th>Domain</th><th>IP</th><th>Root domain</th></tr>")
|
||||
for _, currentDomain := range domains {
|
||||
currentDomain.Mutv4.RLock()
|
||||
copiedIpv4s := currentDomain.Ipv4
|
||||
currentDomain.Mutv4.RUnlock()
|
||||
|
||||
for name, ip := range copiedIpv4s {
|
||||
ctx.WriteString(fmt.Sprintf("<tr><td>A</td><td>%s</td><td>%s</td><td>%s</td><tr>", name, ip, currentDomain.Root))
|
||||
}
|
||||
|
||||
currentDomain.Mutv6.RLock()
|
||||
copiedIpv6s := currentDomain.Ipv6
|
||||
currentDomain.Mutv6.RUnlock()
|
||||
|
||||
for name, ip := range copiedIpv6s {
|
||||
ctx.WriteString(fmt.Sprintf("<tr><td>AAAA</td><td>%s</td><td>%s</td><td>%s</td><tr>", name, ip, currentDomain.Root))
|
||||
}
|
||||
}
|
||||
ctx.WriteString("</table></body></html>")
|
||||
}
|
||||
}
|
||||
|
||||
var ipv4Param = []byte("ipv4")
|
||||
var ipv6Param = []byte("ipv6")
|
||||
var userParam = []byte("user")
|
||||
var passwordParam = []byte("password")
|
||||
|
||||
func updateV4(ctx *fasthttp.RequestCtx) {
|
||||
domain := ctx.UserValue("domain").(string)
|
||||
ipv4 := string(ctx.QueryArgs().PeekBytes(ipv4Param))
|
||||
if ipv4 == "" {
|
||||
ctx.WriteString("Missing ipv4 query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := dns.UpdateIpv4(domain, ipv4)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.WriteString("OK")
|
||||
}
|
||||
|
||||
func updateV6(ctx *fasthttp.RequestCtx) {
|
||||
domain := ctx.UserValue("domain").(string)
|
||||
ipv6 := string(ctx.QueryArgs().PeekBytes(ipv6Param))
|
||||
if ipv6 == "" {
|
||||
ctx.WriteString("Missing ipv6 query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := dns.UpdateIpv6(domain, ipv6)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.WriteString("OK")
|
||||
}
|
||||
|
||||
func authenticatedRequest(request func(ctx *fasthttp.RequestCtx)) func(ctx *fasthttp.RequestCtx) {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
domain, ok := ctx.UserValue("domain").(string)
|
||||
if !ok {
|
||||
ctx.WriteString("Missing domain")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user := string(ctx.QueryArgs().PeekBytes(userParam))
|
||||
if user == "" {
|
||||
ctx.WriteString("Missing user query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
password := string(ctx.QueryArgs().PeekBytes(passwordParam))
|
||||
if user == "" {
|
||||
ctx.WriteString("Missing password query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
authRequest := auth.PasswordAuthenticationRequest{
|
||||
Domain: domain,
|
||||
User: user,
|
||||
Password: password,
|
||||
}
|
||||
|
||||
authenticated, err := auth.IsPasswordAuthenticated(authRequest)
|
||||
if err != nil {
|
||||
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if !authenticated {
|
||||
ctx.SetStatusCode(fasthttp.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
request(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
var r *router.Router
|
||||
|
||||
func Init() {
|
||||
func Init(debugMode bool) {
|
||||
enableDebugMode = debugMode
|
||||
r = router.New()
|
||||
r.GET("/", index)
|
||||
r.GET("/update/{domain}/v4", authenticatedRequest(updateV4))
|
||||
r.GET("/update/{domain}/v6", authenticatedRequest(updateV6))
|
||||
r.GET("/update/{domain}", authenticatedRequest(update))
|
||||
}
|
||||
|
||||
func RunSocket() error {
|
||||
@@ -163,3 +56,157 @@ func RunHTTP() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func index(ctx *fasthttp.RequestCtx) {
|
||||
if !enableDebugMode {
|
||||
ctx.WriteString("Working")
|
||||
} else {
|
||||
domains := dns.Get()
|
||||
ctx.SetContentType("text/html")
|
||||
ctx.WriteString("<!DOCTYPE html><html><head><meta charset='utf-8'><title>gertdns</title></head><body><table><tr><th>Type</th><th>Domain</th><th>IP</th><th>Root domain</th></tr>")
|
||||
for _, currentDomain := range domains {
|
||||
currentDomain.Mutv4.RLock()
|
||||
copiedIpv4s := currentDomain.Ipv4
|
||||
currentDomain.Mutv4.RUnlock()
|
||||
|
||||
for name, ip := range copiedIpv4s {
|
||||
ctx.WriteString(fmt.Sprintf("<tr><td>A</td><td>%s</td><td>%s</td><td>%s</td><tr>", name, ip, currentDomain.Root))
|
||||
}
|
||||
|
||||
currentDomain.Mutv6.RLock()
|
||||
copiedIpv6s := currentDomain.Ipv6
|
||||
currentDomain.Mutv6.RUnlock()
|
||||
|
||||
for name, ip := range copiedIpv6s {
|
||||
ctx.WriteString(fmt.Sprintf("<tr><td>AAAA</td><td>%s</td><td>%s</td><td>%s</td><tr>", name, ip, currentDomain.Root))
|
||||
}
|
||||
}
|
||||
ctx.WriteString("</table></body></html>")
|
||||
}
|
||||
}
|
||||
|
||||
func updateV4(ctx *fasthttp.RequestCtx) {
|
||||
domain := ctx.UserValue("domain").(string)
|
||||
domain = util.ParseDomain(domain)
|
||||
ipv4 := string(ctx.QueryArgs().PeekBytes(ipv4Param))
|
||||
if ipv4 == "" {
|
||||
ctx.WriteString("Missing ipv4 query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := dns.UpdateIpv4(domain, ipv4)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.WriteString("OK")
|
||||
}
|
||||
|
||||
func updateV6(ctx *fasthttp.RequestCtx) {
|
||||
domain := ctx.UserValue("domain").(string)
|
||||
domain = util.ParseDomain(domain)
|
||||
ipv6 := string(ctx.QueryArgs().PeekBytes(ipv6Param))
|
||||
if ipv6 == "" {
|
||||
ctx.WriteString("Missing ipv6 query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err := dns.UpdateIpv6(domain, ipv6)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.WriteString("OK")
|
||||
}
|
||||
|
||||
func update(ctx *fasthttp.RequestCtx) {
|
||||
domain := ctx.UserValue("domain").(string)
|
||||
domain = util.ParseDomain(domain)
|
||||
|
||||
ipv4 := string(ctx.QueryArgs().PeekBytes(ipv4Param))
|
||||
ipv6 := string(ctx.QueryArgs().PeekBytes(ipv6Param))
|
||||
|
||||
if ipv4 == "" && ipv6 == "" {
|
||||
ctx.WriteString("Provide at least one these query parameters: ipv4, ipv6")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if ipv4 != "" {
|
||||
err := dns.UpdateIpv4(domain, ipv4)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ipv6 != "" {
|
||||
err := dns.UpdateIpv6(domain, ipv6)
|
||||
if err != nil {
|
||||
ctx.WriteString(err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.WriteString("OK")
|
||||
}
|
||||
|
||||
func authenticatedRequest(request func(ctx *fasthttp.RequestCtx)) func(ctx *fasthttp.RequestCtx) {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
domain, ok := ctx.UserValue("domain").(string)
|
||||
if !ok {
|
||||
ctx.WriteString("Missing domain")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
domain = util.ParseDomain(domain)
|
||||
|
||||
user := string(ctx.QueryArgs().PeekBytes(userParam))
|
||||
if user == "" {
|
||||
ctx.WriteString("Missing user query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
password := string(ctx.QueryArgs().PeekBytes(passwordParam))
|
||||
if user == "" {
|
||||
ctx.WriteString("Missing password query parameter")
|
||||
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
authRequest := auth.PasswordAuthenticationRequest{
|
||||
Domain: domain,
|
||||
User: user,
|
||||
Password: password,
|
||||
}
|
||||
|
||||
authenticated, err := auth.IsPasswordAuthenticated(authRequest)
|
||||
if err != nil && !authenticated {
|
||||
ctx.WriteString("Authentication failed: " + err.Error())
|
||||
ctx.SetStatusCode(fasthttp.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ctx.WriteString("Internal server error")
|
||||
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if !authenticated {
|
||||
ctx.WriteString("Authentication failed")
|
||||
ctx.SetStatusCode(fasthttp.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
request(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user