116 lines
2.5 KiB
Go
116 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/gorilla/handlers"
|
|
)
|
|
|
|
// Check if a byte is character for number
|
|
func isNumeric(b byte) bool {
|
|
return b >= byte('0') && b <= byte('9')
|
|
}
|
|
|
|
// Default handler, returns 500 Internal Server Error
|
|
func invalidHandler(httpW http.ResponseWriter, httpR *http.Request) {
|
|
httpW.WriteHeader(http.StatusInternalServerError)
|
|
httpW.Write([]byte("Invalid Request\n"))
|
|
}
|
|
|
|
func hasAccess(remoteAddr string) bool {
|
|
// setting.allowedNets will always have at least one element because of how it's defined
|
|
if len(setting.allowedNets) == 0 {
|
|
return true
|
|
}
|
|
|
|
if !strings.Contains(remoteAddr, ":") {
|
|
return false
|
|
}
|
|
|
|
// Remove port from IP and remove brackets that are around IPv6 addresses
|
|
remoteAddr = remoteAddr[0:strings.LastIndex(remoteAddr, ":")]
|
|
remoteAddr = strings.Trim(remoteAddr, "[]")
|
|
|
|
ipObject := net.ParseIP(remoteAddr)
|
|
if ipObject == nil {
|
|
return false
|
|
}
|
|
|
|
for _, net := range setting.allowedNets {
|
|
if net.Contains(ipObject) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Access handler, check to see if client IP in allowed nets, continue if it is, send to invalidHandler if not
|
|
func accessHandler(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(httpW http.ResponseWriter, httpR *http.Request) {
|
|
if hasAccess(httpR.RemoteAddr) {
|
|
next.ServeHTTP(httpW, httpR)
|
|
} else {
|
|
invalidHandler(httpW, httpR)
|
|
}
|
|
})
|
|
}
|
|
|
|
type settingType struct {
|
|
birdSocket string
|
|
listen []string
|
|
allowedNets []*net.IPNet
|
|
tr_bin string
|
|
tr_flags []string
|
|
tr_raw bool
|
|
}
|
|
|
|
var setting settingType
|
|
|
|
// Wrapper of tracer
|
|
func main() {
|
|
parseSettings()
|
|
tracerouteAutodetect()
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
// Prepare HTTP server
|
|
mux.HandleFunc("/", invalidHandler)
|
|
mux.HandleFunc("/bird", birdHandler)
|
|
mux.HandleFunc("/bird6", birdHandler)
|
|
mux.HandleFunc("/traceroute", tracerouteHandler)
|
|
mux.HandleFunc("/traceroute6", tracerouteHandler)
|
|
|
|
for _, listenAddr := range setting.listen {
|
|
go func(addr string) {
|
|
fmt.Printf("Listening on %s...\n", addr)
|
|
|
|
var l net.Listener
|
|
var err error
|
|
|
|
if strings.HasPrefix(addr, "/") {
|
|
// Delete existing socket file, ignore errors (will fail later anyway)
|
|
os.Remove(addr)
|
|
l, err = net.Listen("unix", addr)
|
|
} else {
|
|
if !strings.Contains(addr, ":") {
|
|
addr = ":" + addr
|
|
}
|
|
l, err = net.Listen("tcp", addr)
|
|
}
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
http.Serve(l, handlers.LoggingHandler(os.Stdout, accessHandler(mux)))
|
|
}(listenAddr)
|
|
}
|
|
|
|
select {}
|
|
}
|