mtwebmapper: Only allow update requests from a white list of remote hosts. Defaults to localhost. To allow all hosts use command line option -u=''

This commit is contained in:
Sascha L. Teichmann 2014-11-15 13:40:39 +01:00
parent 52932b0351
commit 4ea51eb744
2 changed files with 73 additions and 1 deletions

View File

@ -8,13 +8,34 @@ import (
"flag"
"fmt"
"log"
"net"
"net/http"
"strings"
"bitbucket.org/s_l_teichmann/mtsatellite/common"
"github.com/gorilla/mux"
)
func ipsFromHosts(hosts string) ([]net.IP, error) {
ips := []net.IP{}
if len(hosts) == 0 { // Empty list: allow all hosts.
return ips, nil
}
for _, host := range strings.Split(hosts, ";") {
if hips, err := net.LookupIP(host); err != nil {
return nil, err
} else {
ips = append(ips, hips...)
}
}
return ips, nil
}
func main() {
var (
webPort int
@ -26,6 +47,7 @@ func main() {
colorsFile string
workers int
transparent bool
updateHosts string
)
flag.IntVar(&webPort, "web-port", 8808, "port of the web server")
flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)")
@ -35,6 +57,10 @@ func main() {
flag.StringVar(&webDir, "w", "web", "static served web files (shorthand)")
flag.StringVar(&mapDir, "map", "map", "directory of prerendered tiles")
flag.StringVar(&mapDir, "m", "map", "directory of prerendered tiles (shorthand)")
flag.StringVar(&updateHosts, "update-hosts", "localhost",
"';' separated list of hosts which are allowed to send map update requests")
flag.StringVar(&updateHosts, "u", "localhost",
"';' separated list of hosts which are allowed to send map update requests (shorthand)")
flag.StringVar(&redisHost, "redis-host", "", "address of the backend Redis server")
flag.StringVar(&redisHost, "rh", "", "address of the backend Redis server (shorthand)")
flag.IntVar(&redisPort, "redis-port", 6379, "port of the backend Redis server")
@ -59,7 +85,14 @@ func main() {
log.Fatalf("ERROR: problem loading colors: %s", err)
}
redisAddress := fmt.Sprintf("%s:%d", redisHost, redisPort)
tu := newTileUpdater(mapDir, redisAddress, colors, transparent, workers)
var allowedUpdateIps []net.IP
if allowedUpdateIps, err = ipsFromHosts(updateHosts); err != nil {
log.Fatalf("ERROR: name resolving problem: %s", err)
}
tu := newTileUpdater(
mapDir, redisAddress, allowedUpdateIps, colors, transparent, workers)
go tu.doUpdates()
router.Path("/update").Methods("POST").Handler(tu)
}

View File

@ -10,13 +10,17 @@ import (
"image"
"image/draw"
"log"
"net"
"net/http"
"path/filepath"
"strconv"
"strings"
"sync"
"github.com/nfnt/resize"
"bytes"
"bitbucket.org/s_l_teichmann/mtsatellite/common"
)
@ -24,6 +28,7 @@ type tileUpdater struct {
changes map[xz]bool
mapDir string
redisAddress string
ips []net.IP
colors *common.Colors
workers int
transparent bool
@ -59,6 +64,7 @@ func (c xz) parent() xzm {
func newTileUpdater(
mapDir, redisAddress string,
ips []net.IP,
colors *common.Colors,
transparent bool,
workers int) *tileUpdater {
@ -66,6 +72,7 @@ func newTileUpdater(
tu := tileUpdater{
mapDir: mapDir,
redisAddress: redisAddress,
ips: ips,
changes: map[xz]bool{},
colors: colors,
transparent: transparent,
@ -74,7 +81,39 @@ func newTileUpdater(
return &tu
}
func (tu *tileUpdater) checkIP(r *http.Request) bool {
if len(tu.ips) == 0 {
return true
}
var host []string
if host = strings.SplitN(r.RemoteAddr, ":", 2); len(host) < 1 {
log.Printf("WARN: cannot extract host from '%s'\n", r.RemoteAddr)
return false
}
var ip net.IP
if ip = net.ParseIP(host[0]); ip == nil {
log.Printf("WARN: cannot get IP for host '%s'.\n", host[0])
return false
}
for i := range tu.ips {
if bytes.Compare(tu.ips[i], ip) == 0 {
return true
}
}
return false
}
func (tu *tileUpdater) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
if !tu.checkIP(r) {
log.Printf("WARN: Unauthorized update request from '%s'", r.RemoteAddr)
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
var err error
var newChanges []xz
decoder := json.NewDecoder(r.Body)