Skip to content
Snippets Groups Projects
Commit bb7649b3 authored by ale's avatar ale
Browse files

Use hostnames in redirects

This allows usage of HTTPS, IPs won't work well in that scenario.
parent 31841975
Branches
No related tags found
1 merge request!2Add SSL functionality
......@@ -23,7 +23,7 @@ import (
)
var (
name = flag.String("name", shortHostname(), "Name for this node")
name = flag.String("name", hostname(), "Name for this node (FQDN)")
publicIPs = util.IPListFlag("public-ip", "Public IP for this machine (may be specified more than once). If unset, the program will try to resolve the local hostname, or it will fall back to inspecting network devices.")
peerIP = util.IPFlag("peer-ip", "Internal IP for this machine (within the cluster), if different from --ip")
httpPort = flag.Int("http-port", 80, "HTTP port")
......@@ -47,11 +47,8 @@ var (
sessionTTL = 5
)
func shortHostname() string {
func hostname() string {
hostname, _ := os.Hostname()
if r := strings.Index(hostname, "."); r >= 0 {
return hostname[:r]
}
return hostname
}
......@@ -84,6 +81,9 @@ func main() {
if *name == "" {
log.Fatal("--name must be set")
}
if !strings.Contains(*name, ".") && *httpsPort > 0 {
log.Fatal("--name must be a FQDN when SSL is enabled")
}
if *domain == "" {
log.Fatal("--domain must be set")
}
......
......@@ -2,7 +2,6 @@ package node
import (
"bytes"
"html/template"
"log"
"net/http"
"sort"
......@@ -93,7 +92,7 @@ func mountsToStatus(mounts []*pb.Mount, nodes []*nodeInfo, icecastMounts map[str
return msl
}
func serveStatusPage(n *Node, w http.ResponseWriter, r *http.Request, tpl *template.Template, domain string) {
func serveStatusPage(n *Node, w http.ResponseWriter, r *http.Request, domain string) {
// Convert the list of nodes to just the status. While we're
// at it, build a map of mount path -> exemplary IcecastMount,
// which we use to show the current song artist / title.
......
......@@ -29,12 +29,17 @@ import (
var (
disableDebugHandlers = flag.Bool("http-disable-debug", false, "disable HTTP /debug handlers")
restrictDebugHandlers = flag.Bool("http-restrict-debug", false, "restrict access to /debug from localhost only")
tpl *template.Template
)
func init() {
tpl = mustParseEmbeddedTemplates()
}
// Build the HTTP handler for the public HTTP endpoint.
func newHTTPHandler(n *Node, icecastPort int, domain string) http.Handler {
mux := http.NewServeMux()
tpl := mustParseEmbeddedTemplates()
// Serve /static/ from builtin assets. Also serve directly
// /favicon.ico using the same mechanism.
......@@ -117,7 +122,7 @@ func newHTTPHandler(n *Node, icecastPort int, domain string) http.Handler {
case r.Method == "SOURCE" || r.Method == "PUT":
sourceHandler.ServeHTTP(w, r)
case r.Method == "GET" && (r.URL.Path == "" || r.URL.Path == "/"):
serveStatusPage(n, w, r, tpl, domain)
serveStatusPage(n, w, r, domain)
case r.Method == "GET":
redirectHandler.ServeHTTP(w, r)
default:
......@@ -184,20 +189,10 @@ func serveRedirect(lb *loadBalancer, mount *pb.Mount, w http.ResponseWriter, r *
return
}
// Pick an IP address to redirect to.
// TODO: replace with an explicit hostname.
targetAddr := randomIPWithMatchingProtocol(targetNode.parsedAddrs, r.RemoteAddr)
if targetAddr == "" {
// This should not happen if the protocol filter in
// the load balancer evaluation did its job properly.
log.Printf("http: %s: protocol unavailable", mount.Path)
http.Error(w, "No nodes available with the right IP protocol", http.StatusServiceUnavailable)
return
}
// Use the node hostname for the redirect (compatible with using SSL certs).
targetURL := url.URL{
Scheme: schemeFromRequest(r),
Host: targetAddr,
Host: targetNode.ep.Name,
Path: autoradio.MountPathToIcecastPath(mount.Path),
}
......
......@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"log"
"math/rand"
"net"
"net/http"
"strconv"
......@@ -309,27 +308,3 @@ func filterIPByProto(ips []ipPort, v6 bool) []ipPort {
}
return candidates
}
// Pick a random IP for the specified proto.
func randomIPByProto(ips []ipPort, v6 bool) ipPort {
candidates := filterIPByProto(ips, v6)
if len(candidates) > 0 {
return candidates[rand.Intn(len(candidates))]
}
return ipPort{}
}
// Select a random IP address from ips, with an IP protocol that
// matches remoteAddr.
func randomIPWithMatchingProtocol(ips []ipPort, remoteAddr string) string {
var isV6 bool
if host, _, err := net.SplitHostPort(remoteAddr); err == nil {
addr := net.ParseIP(host)
isV6 = (addr != nil && addr.To4() == nil)
}
ipp := randomIPByProto(ips, isV6)
if ipp.ip == nil {
return ""
}
return ipp.String()
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment