mirror of
https://github.com/AuxXxilium/docker-ddns-server.git
synced 2024-11-23 23:00:59 +07:00
Added more documentation and prepared some structural changes
This commit is contained in:
parent
d84bcbeef6
commit
ef96496474
@ -2,13 +2,14 @@ package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/model"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/tg123/go-htpasswd"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
@ -27,6 +28,7 @@ type CustomValidator struct {
|
||||
Validator *validator.Validate
|
||||
}
|
||||
|
||||
// Validate implements the Validator.
|
||||
func (cv *CustomValidator) Validate(i interface{}) error {
|
||||
return cv.Validator.Struct(i)
|
||||
}
|
||||
@ -35,6 +37,8 @@ type Error struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Authenticate is the method the website admin user and the host update user have to authenticate against.
|
||||
// To gather admin rights the username password combination must match with the credentials given by the env var.
|
||||
func (h *Handler) Authenticate(username, password string, c echo.Context) (bool, error) {
|
||||
h.AuthHost = nil
|
||||
h.AuthAdmin = false
|
||||
@ -76,6 +80,9 @@ func (h *Handler) authByEnv(username, password string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ParseEnvs parses all needed environment variables:
|
||||
// DDNS_ADMIN_LOGIN: The basic auth login string in htpasswd style.
|
||||
// DDNS_DOMAINS: All domains that will be handled by the dyndns server.
|
||||
func (h *Handler) ParseEnvs() error {
|
||||
h.Config = Envs{}
|
||||
h.Config.AdminLogin = os.Getenv("DDNS_ADMIN_LOGIN")
|
||||
@ -91,6 +98,7 @@ func (h *Handler) ParseEnvs() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitDB creates an empty database and creates all tables if there isn't already one, or opens the existing one.
|
||||
func (h *Handler) InitDB() (err error) {
|
||||
if _, err := os.Stat("database"); os.IsNotExist(err) {
|
||||
err = os.MkdirAll("database", os.ModePerm)
|
||||
|
@ -2,18 +2,26 @@ package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/model"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/nswrapper"
|
||||
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/model"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
UNAUTHORIZED = "You are not allowed to view that content"
|
||||
)
|
||||
|
||||
// GetHost fetches a host from the database by "id".
|
||||
func (h *Handler) GetHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
@ -30,9 +38,10 @@ func (h *Handler) GetHost(c echo.Context) (err error) {
|
||||
return c.JSON(http.StatusOK, id)
|
||||
}
|
||||
|
||||
// ListHosts fetches all hosts from database and lists them on the website.
|
||||
func (h *Handler) ListHosts(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
hosts := new([]model.Host)
|
||||
@ -45,9 +54,10 @@ func (h *Handler) ListHosts(c echo.Context) (err error) {
|
||||
})
|
||||
}
|
||||
|
||||
// AddHost just renders the "add host" website.
|
||||
func (h *Handler) AddHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
return c.Render(http.StatusOK, "edithost", echo.Map{
|
||||
@ -56,9 +66,10 @@ func (h *Handler) AddHost(c echo.Context) (err error) {
|
||||
})
|
||||
}
|
||||
|
||||
// EditHost fetches a host by "id" and renders the "edit host" website.
|
||||
func (h *Handler) EditHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
@ -78,9 +89,12 @@ func (h *Handler) EditHost(c echo.Context) (err error) {
|
||||
})
|
||||
}
|
||||
|
||||
// CreateHost validates the host data from the "add host" website,
|
||||
// adds the host entry to the database,
|
||||
// and adds the entry to the DNS server.
|
||||
func (h *Handler) CreateHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
host := &model.Host{}
|
||||
@ -98,12 +112,12 @@ func (h *Handler) CreateHost(c echo.Context) (err error) {
|
||||
|
||||
// If a ip is set create dns entry
|
||||
if host.Ip != "" {
|
||||
ipType := getIPType(host.Ip)
|
||||
ipType := nswrapper.GetIPType(host.Ip)
|
||||
if ipType == "" {
|
||||
return c.JSON(http.StatusBadRequest, &Error{fmt.Sprintf("ip %s is not a valid ip", host.Ip)})
|
||||
}
|
||||
|
||||
if err = h.updateRecord(host.Hostname, host.Ip, ipType, host.Domain, host.Ttl); err != nil {
|
||||
if err = nswrapper.UpdateRecord(host.Hostname, host.Ip, ipType, host.Domain, host.Ttl); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, &Error{err.Error()})
|
||||
}
|
||||
}
|
||||
@ -111,9 +125,12 @@ func (h *Handler) CreateHost(c echo.Context) (err error) {
|
||||
return c.JSON(http.StatusOK, host)
|
||||
}
|
||||
|
||||
// UpdateHost validates the host data from the "edit host" website,
|
||||
// and compares the host data with the entry in the database by "id".
|
||||
// If anything has changed the database and DNS entries for the host will be updated.
|
||||
func (h *Handler) UpdateHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
hostUpdate := &model.Host{}
|
||||
@ -142,12 +159,12 @@ func (h *Handler) UpdateHost(c echo.Context) (err error) {
|
||||
|
||||
// If ip or ttl changed update dns entry
|
||||
if forceRecordUpdate {
|
||||
ipType := getIPType(host.Ip)
|
||||
ipType := nswrapper.GetIPType(host.Ip)
|
||||
if ipType == "" {
|
||||
return c.JSON(http.StatusBadRequest, &Error{fmt.Sprintf("ip %s is not a valid ip", host.Ip)})
|
||||
}
|
||||
|
||||
if err = h.updateRecord(host.Hostname, host.Ip, ipType, host.Domain, host.Ttl); err != nil {
|
||||
if err = nswrapper.UpdateRecord(host.Hostname, host.Ip, ipType, host.Domain, host.Ttl); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, &Error{err.Error()})
|
||||
}
|
||||
}
|
||||
@ -155,9 +172,11 @@ func (h *Handler) UpdateHost(c echo.Context) (err error) {
|
||||
return c.JSON(http.StatusOK, host)
|
||||
}
|
||||
|
||||
// DeleteHost fetches a host entry from the database by "id"
|
||||
// and deletes the database and DNS server entry to it.
|
||||
func (h *Handler) DeleteHost(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
@ -185,23 +204,26 @@ func (h *Handler) DeleteHost(c echo.Context) (err error) {
|
||||
return c.JSON(http.StatusBadRequest, &Error{err.Error()})
|
||||
}
|
||||
|
||||
if err = h.deleteRecord(host.Hostname, host.Domain); err != nil {
|
||||
if err = nswrapper.DeleteRecord(host.Hostname, host.Domain); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, &Error{err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, id)
|
||||
}
|
||||
|
||||
// UpdateIP implements the update method called by the routers.
|
||||
// Hostname, IP and senders IP are validated, a log entry is created
|
||||
// and finally if everything is ok, the DNS Server will be updated
|
||||
func (h *Handler) UpdateIP(c echo.Context) (err error) {
|
||||
if h.AuthHost == nil {
|
||||
return c.String(http.StatusBadRequest, "badauth\n")
|
||||
}
|
||||
|
||||
log := &model.Log{Status: false, Host: *h.AuthHost, TimeStamp: time.Now(), UserAgent: shrinkUserAgent(c.Request().UserAgent())}
|
||||
log := &model.Log{Status: false, Host: *h.AuthHost, TimeStamp: time.Now(), UserAgent: nswrapper.ShrinkUserAgent(c.Request().UserAgent())}
|
||||
log.SentIP = c.QueryParam(("myip"))
|
||||
|
||||
// Get caller IP
|
||||
log.CallerIP, err = getCallerIP(c.Request())
|
||||
log.CallerIP, err = nswrapper.GetCallerIP(c.Request())
|
||||
if log.CallerIP == "" {
|
||||
log.CallerIP, _, err = net.SplitHostPort(c.Request().RemoteAddr)
|
||||
if err != nil {
|
||||
@ -226,10 +248,10 @@ func (h *Handler) UpdateIP(c echo.Context) (err error) {
|
||||
}
|
||||
|
||||
// Get IP type
|
||||
ipType := getIPType(log.SentIP)
|
||||
ipType := nswrapper.GetIPType(log.SentIP)
|
||||
if ipType == "" {
|
||||
log.SentIP = log.CallerIP
|
||||
ipType = getIPType(log.SentIP)
|
||||
ipType = nswrapper.GetIPType(log.SentIP)
|
||||
if ipType == "" {
|
||||
log.Message = "Bad Request: Sent IP is invalid"
|
||||
if err = h.CreateLogEntry(log); err != nil {
|
||||
@ -241,7 +263,7 @@ func (h *Handler) UpdateIP(c echo.Context) (err error) {
|
||||
}
|
||||
|
||||
// add/update DNS record
|
||||
if err = h.updateRecord(log.Host.Hostname, log.SentIP, ipType, log.Host.Domain, log.Host.Ttl); err != nil {
|
||||
if err = nswrapper.UpdateRecord(log.Host.Hostname, log.SentIP, ipType, log.Host.Domain, log.Host.Ttl); err != nil {
|
||||
log.Message = fmt.Sprintf("DNS error: %v", err)
|
||||
if err = h.CreateLogEntry(log); err != nil {
|
||||
fmt.Println(err)
|
||||
|
@ -1,12 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/model"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/model"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// CreateLogEntry simply adds a log entry to the database.
|
||||
func (h *Handler) CreateLogEntry(log *model.Log) (err error) {
|
||||
if err = h.DB.Create(log).Error; err != nil {
|
||||
return err
|
||||
@ -15,9 +17,10 @@ func (h *Handler) CreateLogEntry(log *model.Log) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShowLogs fetches all log entries from all hosts and renders them to the website.
|
||||
func (h *Handler) ShowLogs(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
logs := new([]model.Log)
|
||||
@ -30,9 +33,10 @@ func (h *Handler) ShowLogs(c echo.Context) (err error) {
|
||||
})
|
||||
}
|
||||
|
||||
// ShowHostLogs fetches all log entries of a specific host by "id" and renders them to the website.
|
||||
func (h *Handler) ShowHostLogs(c echo.Context) (err error) {
|
||||
if !h.AuthAdmin {
|
||||
return c.JSON(http.StatusUnauthorized, &Error{"You are not allow to view that content"})
|
||||
return c.JSON(http.StatusUnauthorized, &Error{UNAUTHORIZED})
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
|
@ -4,20 +4,22 @@ import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// ValidIP4 tells you if a given string is a valid IPv4 address.
|
||||
func ValidIP4(ipAddress string) bool {
|
||||
testInput := net.ParseIP(ipAddress)
|
||||
if testInput == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return (testInput.To4() != nil)
|
||||
return testInput.To4() != nil
|
||||
}
|
||||
|
||||
// ValidIP6 tells you if a given string is a valid IPv6 address.
|
||||
func ValidIP6(ip6Address string) bool {
|
||||
testInputIP6 := net.ParseIP(ip6Address)
|
||||
if testInputIP6 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return (testInputIP6.To16() != nil)
|
||||
return testInputIP6.To16() != nil
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// Host is a dns host entry.
|
||||
type Host struct {
|
||||
gorm.Model
|
||||
Hostname string `gorm:"unique_index:idx_host_domain;not null" form:"hostname" validate:"required,hostname"`
|
||||
@ -17,6 +18,8 @@ type Host struct {
|
||||
Password string `form:"password" validate:"min=8"`
|
||||
}
|
||||
|
||||
// UpdateHost updates all fields of a host entry
|
||||
// and sets a new LastUpdate date.
|
||||
func (h *Host) UpdateHost(updateHost *Host) (updateRecord bool) {
|
||||
updateRecord = false
|
||||
if h.Ip != updateHost.Ip || h.Ttl != updateHost.Ttl {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// Log defines a log entry.
|
||||
type Log struct {
|
||||
gorm.Model
|
||||
Status bool
|
||||
|
@ -1,93 +1,18 @@
|
||||
package handler
|
||||
package nswrapper
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/ipparser"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/benjaminbear/docker-ddns-server/dyndns/ipparser"
|
||||
)
|
||||
|
||||
func (h *Handler) updateRecord(hostname string, ipAddr string, addrType string, zone string, ttl int) error {
|
||||
fmt.Printf("%s record update request: %s -> %s\n", addrType, hostname, ipAddr)
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "dyndns")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(f.Name())
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
w.WriteString(fmt.Sprintf("server %s\n", "localhost"))
|
||||
w.WriteString(fmt.Sprintf("zone %s\n", zone))
|
||||
w.WriteString(fmt.Sprintf("update delete %s.%s %s\n", hostname, zone, addrType))
|
||||
w.WriteString(fmt.Sprintf("update add %s.%s %v %s %s\n", hostname, zone, ttl, addrType, ipAddr))
|
||||
w.WriteString("send\n")
|
||||
|
||||
w.Flush()
|
||||
f.Close()
|
||||
|
||||
cmd := exec.Command("/usr/bin/nsupdate", f.Name())
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", err, stderr.String())
|
||||
}
|
||||
|
||||
if out.String() != "" {
|
||||
return fmt.Errorf(out.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) deleteRecord(hostname string, zone string) error {
|
||||
fmt.Printf("record delete request: %s\n", hostname)
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "dyndns")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(f.Name())
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
w.WriteString(fmt.Sprintf("server %s\n", "localhost"))
|
||||
w.WriteString(fmt.Sprintf("zone %s\n", zone))
|
||||
w.WriteString(fmt.Sprintf("update delete %s.%s\n", hostname, zone))
|
||||
w.WriteString("send\n")
|
||||
|
||||
w.Flush()
|
||||
f.Close()
|
||||
|
||||
cmd := exec.Command("/usr/bin/nsupdate", f.Name())
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", err, stderr.String())
|
||||
}
|
||||
|
||||
if out.String() != "" {
|
||||
return fmt.Errorf(out.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIPType(ipAddr string) string {
|
||||
// GetIPType finds out if the IP is IPv4 or IPv6
|
||||
func GetIPType(ipAddr string) string {
|
||||
if ipparser.ValidIP4(ipAddr) {
|
||||
return "A"
|
||||
} else if ipparser.ValidIP6(ipAddr) {
|
||||
@ -97,7 +22,9 @@ func getIPType(ipAddr string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func getCallerIP(r *http.Request) (string, error) {
|
||||
// GetCallerIP searches for the "real" IP senders has actually.
|
||||
// If its a private address we won't use it.
|
||||
func GetCallerIP(r *http.Request) (string, error) {
|
||||
fmt.Println("request", r.Header)
|
||||
for _, h := range []string{"X-Real-Ip", "X-Forwarded-For"} {
|
||||
addresses := strings.Split(r.Header.Get(h), ",")
|
||||
@ -117,6 +44,13 @@ func getCallerIP(r *http.Request) (string, error) {
|
||||
return "", errors.New("no match")
|
||||
}
|
||||
|
||||
// ShrinkUserAgent simply cuts the user agent information if its too long to display.
|
||||
func ShrinkUserAgent(agent string) string {
|
||||
agentParts := strings.Split(agent, " ")
|
||||
|
||||
return agentParts[0]
|
||||
}
|
||||
|
||||
// ipRange - a structure that holds the start and end of a range of ip addresses
|
||||
type ipRange struct {
|
||||
start net.IP
|
||||
@ -173,9 +107,3 @@ func isPrivateSubnet(ipAddress net.IP) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func shrinkUserAgent(agent string) string {
|
||||
agentParts := strings.Split(agent, " ")
|
||||
|
||||
return agentParts[0]
|
||||
}
|
85
dyndns/nswrapper/update.go
Normal file
85
dyndns/nswrapper/update.go
Normal file
@ -0,0 +1,85 @@
|
||||
package nswrapper
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// UpdateRecord builds a nsupdate file and updates a record by executing it with nsupdate.
|
||||
func UpdateRecord(hostname string, ipAddr string, addrType string, zone string, ttl int) error {
|
||||
fmt.Printf("%s record update request: %s -> %s\n", addrType, hostname, ipAddr)
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "dyndns")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(f.Name())
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
w.WriteString(fmt.Sprintf("server %s\n", "localhost"))
|
||||
w.WriteString(fmt.Sprintf("zone %s\n", zone))
|
||||
w.WriteString(fmt.Sprintf("update delete %s.%s %s\n", hostname, zone, addrType))
|
||||
w.WriteString(fmt.Sprintf("update add %s.%s %v %s %s\n", hostname, zone, ttl, addrType, ipAddr))
|
||||
w.WriteString("send\n")
|
||||
|
||||
w.Flush()
|
||||
f.Close()
|
||||
|
||||
cmd := exec.Command("/usr/bin/nsupdate", f.Name())
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", err, stderr.String())
|
||||
}
|
||||
|
||||
if out.String() != "" {
|
||||
return fmt.Errorf(out.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteRecord builds a nsupdate file and deletes a record by executing it with nsupdate.
|
||||
func DeleteRecord(hostname string, zone string) error {
|
||||
fmt.Printf("record delete request: %s\n", hostname)
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "dyndns")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(f.Name())
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
w.WriteString(fmt.Sprintf("server %s\n", "localhost"))
|
||||
w.WriteString(fmt.Sprintf("zone %s\n", zone))
|
||||
w.WriteString(fmt.Sprintf("update delete %s.%s\n", hostname, zone))
|
||||
w.WriteString("send\n")
|
||||
|
||||
w.Flush()
|
||||
f.Close()
|
||||
|
||||
cmd := exec.Command("/usr/bin/nsupdate", f.Name())
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", err, stderr.String())
|
||||
}
|
||||
|
||||
if out.String() != "" {
|
||||
return fmt.Errorf(out.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user