Skip to content

Commit

Permalink
IsLocalHost: support host:port
Browse files Browse the repository at this point in the history
Without this patch IsLocalHost does not work for URLs with port specified i.e. it works for `http://localhost` but does not work for `http://localhost:80` or `http://localhost:10000`.

Fixes elazarl#487
  • Loading branch information
mmatczuk committed Nov 8, 2022
1 parent a0805db commit dd259cd
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
23 changes: 15 additions & 8 deletions dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,22 @@ func ReqHostIs(hosts ...string) ReqConditionFunc {
}
}

var localHostIpv4 = regexp.MustCompile(`127\.0\.0\.\d+`)

// IsLocalHost checks whether the destination host is explicitly local host
// (buggy, there can be IPv6 addresses it doesn't catch)
// IsLocalHost checks whether the destination host is localhost.
var IsLocalHost ReqConditionFunc = func(req *http.Request, ctx *ProxyCtx) bool {
return req.URL.Host == "::1" ||
req.URL.Host == "0:0:0:0:0:0:0:1" ||
localHostIpv4.MatchString(req.URL.Host) ||
req.URL.Host == "localhost"
h := req.URL.Hostname()
if h == "localhost" {
return true
}
if ip := net.ParseIP(h); ip != nil {
return ip.IsLoopback()
}

// In case of IPv6 without a port number Hostname() sometimes returns the invalid value.
if ip := net.ParseIP(req.URL.Host); ip != nil {
return ip.IsLoopback()
}

return false
}

// UrlMatches returns a ReqCondition testing whether the destination URL
Expand Down
47 changes: 47 additions & 0 deletions dispatcher_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package goproxy

import (
"net"
"net/http"
"strings"
"testing"
)

func TestIsLocalHost(t *testing.T) {
hosts := []string{
"localhost",
"127.0.0.1",
"127.0.0.7",
"::ffff:127.0.0.1",
"::ffff:127.0.0.7",
"::1",
"0:0:0:0:0:0:0:1",
}
ports := []string{
"",
"80",
"443",
}

for _, host := range hosts {
for _, port := range ports {
if port == "" && strings.HasPrefix(host, "::ffff:") {
continue
}

addr := host
if port != "" {
addr = net.JoinHostPort(host, port)
}
t.Run(addr, func(t *testing.T) {
req, err := http.NewRequest("GET", "http://"+addr, http.NoBody)
if err != nil {
t.Fatal(err)
}
if !IsLocalHost(req, nil) {
t.Fatal("expected true")
}
})
}
}
}

0 comments on commit dd259cd

Please sign in to comment.