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

Run a simple httputil.ReverseProxy with TLS connections

We can't do low-level splice() since we don't have access to the raw
socket in the TLS case. This should work for clients though (maybe not
for sources).
parent bb7649b3
Branches
No related tags found
1 merge request!2Add SSL functionality
......@@ -291,8 +291,8 @@ func newHTTPServer(name, addr string, h http.Handler) *httpServer {
Handler: h,
ReadTimeout: 10 * time.Second,
ReadHeaderTimeout: 3 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
//WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
},
name: name,
}
......
......@@ -14,6 +14,7 @@ import (
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"sync"
......@@ -102,6 +103,18 @@ func doIcecastProxy(rw http.ResponseWriter, req *http.Request, target *url.URL,
outreq.Header.Set("X-Forwarded-For", clientIP)
}
// SSL requests can't be hijacked, so we just fire up a normal
// httputil.ReverseProxy (not fully functional for sources, but
// meh).
if req.TLS != nil {
log.Printf("TLS connection, switching to dumb reverse proxy mode")
u := *outreq.URL
u.Path = "/"
rp := httputil.NewSingleHostReverseProxy(&u)
rp.ServeHTTP(rw, outreq)
return
}
// Create the upstream connection and write the HTTP request
// to it.
upstream, err := dialer.Dial("tcp", outreq.URL.Host)
......@@ -147,7 +160,7 @@ func doIcecastProxy(rw http.ResponseWriter, req *http.Request, target *url.URL,
}
if conn == nil {
log.Printf("http: proxy error: could not find hijackable connection")
rw.WriteHeader(http.StatusInternalServerError)
http.Error(rw, "could not find hijackable connection", http.StatusInternalServerError)
return
}
defer conn.Close()
......@@ -156,21 +169,17 @@ func doIcecastProxy(rw http.ResponseWriter, req *http.Request, target *url.URL,
}
// Run two-way proxying.
handleProxy(conn.(*net.TCPConn), upstream.(*net.TCPConn), streamName)
handleProxy(conn, upstream, streamName)
}
// Copy data between two network connections. On recent Go versions
// (>1.11), this is quite fast as io.CopyBuffer uses the splice()
// system call internally (in exchange we lose the ability to figure
// out which end of the connection is the source of the error).
func copyStream(tag string, out, in *net.TCPConn, promCounter prometheus.Counter, cntr *uint64) {
func copyStream(tag string, out io.WriteCloser, in io.ReadCloser, promCounter prometheus.Counter, cntr *uint64) {
buf := getBuf()
defer releaseBuf(buf)
// We used to do this in order to support half-closed connections.
//defer in.CloseRead() //nolint
//defer out.CloseWrite() //nolint
// Instead we do this and shut down the entire connection on error.
// We end up calling Close() twice but that's not a huge problem.
defer in.Close() //nolint
......@@ -195,7 +204,7 @@ func isCloseError(err error) bool {
// Simple two-way TCP proxy that copies data in both directions and
// can shutdown each direction of the connection independently.
func handleProxy(conn *net.TCPConn, upstream *net.TCPConn, streamName string) {
func handleProxy(conn, upstream io.ReadWriteCloser, streamName string) {
l := streamListeners.WithLabelValues(streamName)
l.Inc()
var wg sync.WaitGroup
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment