| package main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| "net" |
| "net/http" |
| "net/http/httputil" |
| ) |
| |
| var ( |
| flagUpstream string |
| flagUpstreamHost string |
| flagDownstreamHost string |
| flagListen string |
| ) |
| |
| func newProxy() http.Handler { |
| proxy := httputil.ReverseProxy{ |
| Director: func(r *http.Request) { |
| r.URL.Scheme = "http" |
| r.URL.Host = flagUpstream |
| r.Host = flagUpstreamHost |
| // MMR reads this field and prioritizes it over the Host header. |
| r.Header.Set("X-Forwarded-Host", flagUpstreamHost) |
| }, |
| } |
| |
| acl := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| remote := r.RemoteAddr |
| sip := r.Header.Get("Hscloud-Nic-Source-IP") |
| sport := r.Header.Get("Hscloud-Nic-Source-Port") |
| if sip != "" && sport != "" { |
| remote = net.JoinHostPort(sip, sport) |
| r.Header.Set("X-Forwarded-For", remote) |
| } |
| log.Printf("%s %s %s", remote, r.Method, r.URL.Path) |
| |
| // ... during federation requests, Host is foo.example.com:443, strip |
| // that out if that's the case. Ignore port number, we don't care about |
| // it. |
| host, _, err := net.SplitHostPort(r.Host) |
| if err != nil { |
| // Error can mean many things, but generally it means 'no port', or |
| // a very malformed host. Regardless, just default to the raw |
| // value, we explicitly check it against a required host value |
| // further down |
| host = r.Host |
| } |
| |
| if host != flagDownstreamHost { |
| log.Printf("Invalid host requested %q, wanted %q", r.Host, flagDownstreamHost) |
| w.WriteHeader(http.StatusBadRequest) |
| fmt.Fprintf(w, "invalid host\n") |
| return |
| } |
| proxy.ServeHTTP(w, r) |
| }) |
| |
| return acl |
| } |
| |
| func main() { |
| flag.StringVar(&flagUpstreamHost, "upstream_host", "hackerspace.pl", "Upstream Host header, as sent to upstream") |
| flag.StringVar(&flagUpstream, "upstream", "foo.bar.svc.cluster.local:8080", "Address and port to reach upstream") |
| flag.StringVar(&flagDownstreamHost, "downstream_host", "matrix.hackerspace.pl", "Downstream Host header, as requested by client traffic") |
| flag.StringVar(&flagListen, "listen", ":8080", "Address to listen at for downstream traffic") |
| flag.Parse() |
| |
| log.Printf("Starting media-repo-proxy") |
| |
| proxy := newProxy() |
| |
| log.Printf("Listening on %s...", flagListen) |
| if err := http.ListenAndServe(flagListen, proxy); err != nil { |
| log.Printf("Listen failed: %v", err) |
| } |
| } |