324 lines
6.8 KiB
Go
324 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/gorilla/mux"
|
|
log "github.com/sirupsen/logrus"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
|
|
type HttpServer struct {
|
|
_server *http.Server
|
|
_database *Database
|
|
_oauth *OAuth2
|
|
_renderer *Renderer
|
|
_dnsclient *DnsUpdate
|
|
_ipAddresses map[string][]string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type GuiSetting struct {
|
|
FilterString *string
|
|
}
|
|
|
|
func getIP(r *http.Request) (string, error) {
|
|
var host string
|
|
forwarded := r.Header.Get("X-FORWARDED-FOR")
|
|
if forwarded != "" {
|
|
host = forwarded
|
|
} else {
|
|
host = r.RemoteAddr
|
|
}
|
|
|
|
host,_ , err := net.SplitHostPort(host)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return host, nil
|
|
}
|
|
|
|
func (h *HttpServer) doaction(w http.ResponseWriter, r *http.Request, params *AdminPageParams){
|
|
if action := r.URL.Query().Get("action"); action != "" {
|
|
|
|
switch action {
|
|
case "update":
|
|
host := r.URL.Query().Get("host")
|
|
ip := r.URL.Query().Get("ip")
|
|
|
|
if !h._database.ExistHost(host) {
|
|
params.Alerts = append(params.Alerts, Alert{Type:"error", Message: fmt.Sprintf("host %s does not exist", host)})
|
|
break
|
|
}
|
|
err := h._dnsclient.Update(host, ip)
|
|
if err != nil {
|
|
params.Alerts = append(params.Alerts, Alert{Type:"error", Message: err.Error()})
|
|
} else {
|
|
params.Alerts = append(params.Alerts, Alert{Type:"success", Message: "successfully updated host"})
|
|
}
|
|
break
|
|
|
|
case "delete":
|
|
host := r.URL.Query().Get("host")
|
|
log.Info("deleting host " + host)
|
|
h._database.DeleteHost(host)
|
|
h._dnsclient.Remove(host)
|
|
delete(h._ipAddresses, host)
|
|
break
|
|
|
|
case "externalresolve":
|
|
host := r.URL.Query().Get("host")
|
|
ips, err := h._dnsclient.ExternalResolve(host)
|
|
if err != nil {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "error",
|
|
Message: fmt.Sprintf("host %s could not be resolved", host),
|
|
})
|
|
} else {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "success",
|
|
Message: fmt.Sprintf("host %s resolved to following addresses:\n %s", host, fmt.Sprint(ips)),
|
|
})
|
|
}
|
|
case "resolve":
|
|
host := r.URL.Query().Get("host")
|
|
ipAddresses, err := h._dnsclient.Resolve(host)
|
|
if err == nil && len(ipAddresses) > 0 {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "success",
|
|
Message: fmt.Sprintf("host %s resolved to following addresses:\n %s", host, fmt.Sprint(ipAddresses)),
|
|
})
|
|
h._ipAddresses[host] = ipAddresses
|
|
} else {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "error",
|
|
Message: fmt.Sprintf("host %s could not be resolved", host),
|
|
})
|
|
delete(h._ipAddresses, host)
|
|
}
|
|
|
|
|
|
case "add":
|
|
host := r.URL.Query().Get("host")
|
|
_, err := h._database.CreateHost(host)
|
|
if err == nil {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "success",
|
|
Message: fmt.Sprintf("created host %s", host),
|
|
})
|
|
} else {
|
|
params.Alerts = append(params.Alerts, Alert{
|
|
Type: "error",
|
|
Message: fmt.Sprintf("could not create host %s.\n reason: %s", host, err.Error()),
|
|
})
|
|
}
|
|
break
|
|
|
|
|
|
}
|
|
} else {
|
|
}
|
|
}
|
|
|
|
func (h *HttpServer) doguisetting(w http.ResponseWriter, r *http.Request) *GuiSetting{
|
|
settings := new(GuiSetting)
|
|
settings.FilterString = nil
|
|
|
|
if setting := r.URL.Query().Get("setting"); setting != "" {
|
|
|
|
switch setting {
|
|
case "filter":
|
|
host := r.URL.Query().Get("host")
|
|
settings.FilterString = &host
|
|
break
|
|
}
|
|
|
|
}
|
|
return settings
|
|
}
|
|
|
|
|
|
func (h *HttpServer) adminPage(w http.ResponseWriter, r *http.Request) {
|
|
token, ok := h._oauth.checkOAuth(w, r, true)
|
|
if !ok { return }
|
|
|
|
params := new(AdminPageParams)
|
|
params.Alerts = make([]Alert, 0)
|
|
params.Hosts = make(map[string]string)
|
|
params.IpAddresses = h._ipAddresses
|
|
|
|
|
|
h.doaction(w,r, params)
|
|
settings := h.doguisetting(w,r)
|
|
claims, _ := h._oauth.GetClaims(w, token)
|
|
|
|
|
|
params.Email = claims.Email
|
|
params.Profile = claims.Profile
|
|
|
|
if settings.FilterString != nil {
|
|
params.Hosts = h._database.GetExistingHosts(*settings.FilterString)
|
|
params.Alerts = append(
|
|
params.Alerts,
|
|
Alert{
|
|
Type: "info",
|
|
Message: fmt.Sprintf("returned %d hosts", len(params.Hosts)),
|
|
})
|
|
} else {
|
|
params.Hosts = h._database.GetExistingHosts("")
|
|
}
|
|
|
|
h._renderer.RenderAdminPage(w, params)
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h *HttpServer) registerHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if _, ok := h._oauth.checkOAuth(w, r, false); ok {
|
|
return
|
|
}
|
|
|
|
host := r.URL.Query().Get("host")
|
|
|
|
clientip, err := getIP(r)
|
|
if err != nil { log.Fatal(err) }
|
|
|
|
if h._database.IsBannedHost(clientip) {
|
|
h._database.IncrementBanHost(clientip)
|
|
log.Error("host ", clientip, " is banned!")
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
|
|
if h._database.ExistHost(host) {
|
|
h._database.IncrementBanHost(clientip)
|
|
w.WriteHeader(http.StatusNotAcceptable)
|
|
return
|
|
}
|
|
|
|
token, err := h._database.CreateHost(host)
|
|
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
ret := map[string]string {
|
|
"host": host,
|
|
"token": token,
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(ret)
|
|
}
|
|
|
|
func (h *HttpServer) updateHandler(w http.ResponseWriter, r *http.Request) {
|
|
hosts := r.URL.Query()["host"]
|
|
tokens := r.URL.Query()["token"]
|
|
myips := r.URL.Query()["myip"]
|
|
var myip string
|
|
|
|
clientip, err := getIP(r)
|
|
|
|
if h._database.IsBannedHost(clientip) {
|
|
h._database.IncrementBanHost(clientip)
|
|
log.Error("host ", clientip, " is banned!")
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if len(hosts) == 0 {
|
|
h._database.IncrementBanHost(clientip)
|
|
w.WriteHeader(http.StatusNotAcceptable)
|
|
return
|
|
}
|
|
|
|
if len(tokens) == 0 {
|
|
h._database.IncrementBanHost(clientip)
|
|
w.WriteHeader(http.StatusNotAcceptable)
|
|
return
|
|
}
|
|
|
|
if len(myips) == 0 {
|
|
myip = clientip
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
} else {
|
|
myip = myips[0]
|
|
}
|
|
|
|
host := hosts[0]
|
|
token := tokens[0]
|
|
|
|
if !h._database.Authorize(host, token) {
|
|
h._database.IncrementBanHost(clientip)
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
log.Info("authorization successful.")
|
|
log.Info("will update host ", host, " ip ", myip)
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
func (h *HttpServer) Listen() {
|
|
h._server.ListenAndServe()
|
|
}
|
|
|
|
func CreateHttpServer(config *Config) *HttpServer {
|
|
|
|
var httpserver *HttpServer
|
|
var err error
|
|
|
|
httpserver = new(HttpServer)
|
|
|
|
r := mux.NewRouter()
|
|
|
|
httpserver._ipAddresses = make(map[string][]string)
|
|
|
|
httpserver._renderer, err = CreateRenderer(config)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
httpserver._database, err = CreateDatabase(config)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
httpserver._oauth, err = CreateOAuth2(config)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
httpserver._dnsclient = NewTestInstance()
|
|
|
|
httpserver._server = &http.Server{
|
|
Addr: config.Addr,
|
|
Handler: r,
|
|
}
|
|
|
|
r.HandleFunc("/register", httpserver.registerHandler)
|
|
r.HandleFunc("/update", httpserver.updateHandler)
|
|
r.HandleFunc("/admin", httpserver.adminPage)
|
|
|
|
return httpserver
|
|
}
|