Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ipfilter argument for filtering by incoming requests source IP #51

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var (
keyFile = flag.String("key", "", "path to a private key file. If not provided, ssl-proxy will generate one for you in ~/.ssl-proxy/")
domain = flag.String("domain", "", "domain to mint letsencrypt certificates for. Usage of this parameter implies acceptance of the LetsEncrypt terms of service.")
redirectHTTP = flag.Bool("redirectHTTP", false, "if true, redirects http requests from port 80 to https at your fromURL")
ipFilter = flag.String("ipfilter", "", "source IP address to filter incoming requests on. If not provided allow all IP")
)

const (
Expand Down Expand Up @@ -81,7 +82,7 @@ func main() {
}

// Setup reverse proxy ServeMux
p := reverseproxy.Build(toURL)
p := reverseproxy.Build(toURL, *ipFilter)
mux := http.NewServeMux()
mux.Handle("/", p)

Expand Down
42 changes: 25 additions & 17 deletions reverseproxy/reverseproxy.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
package reverseproxy

import (
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)

// Build initializes and returns a new ReverseProxy instance suitable for SSL proxying
func Build(toURL *url.URL) *httputil.ReverseProxy {
func Build(toURL *url.URL, ipFilter string) *httputil.ReverseProxy {
localProxy := &httputil.ReverseProxy{}
addProxyHeaders := func(req *http.Request) {
req.Header.Set(http.CanonicalHeaderKey("X-Forwarded-Proto"), "https")
req.Header.Set(http.CanonicalHeaderKey("X-Forwarded-Port"), "443") // TODO: inherit another port if needed
}
localProxy.Director = newDirector(toURL, addProxyHeaders)
localProxy.Director = newDirector(toURL, ipFilter, addProxyHeaders)

return localProxy
}

// newDirector creates a base director that should be exactly what http.NewSingleHostReverseProxy() creates, but allows
// for the caller to supply and extraDirector function to decorate to request to the downstream server
func newDirector(target *url.URL, extraDirector func(*http.Request)) func(*http.Request) {
func newDirector(target *url.URL, ipFilter string, extraDirector func(*http.Request)) func(*http.Request) {
targetQuery := target.RawQuery
return func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
remoteIp, _, _ := net.SplitHostPort(req.RemoteAddr)
if ipFilter == "" || remoteIp == ipFilter {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}

if extraDirector != nil {
extraDirector(req)
if extraDirector != nil {
extraDirector(req)
}
} else {
// send to black hole
req.URL.Host = "127.0.0.1:0"
req.URL.Scheme = "http"
}
}
}
Expand Down