restrict private IP access

This commit is contained in:
nkanaev
2025-10-02 10:16:35 +01:00
parent ac9b635ed8
commit 9f93298cf9
4 changed files with 71 additions and 0 deletions

View File

@@ -4,6 +4,7 @@
- (new) more auto-refresh options: 12h & 24h (thanks to @aswerkljh for suggestion) - (new) more auto-refresh options: 12h & 24h (thanks to @aswerkljh for suggestion)
- (fix) smooth scrolling on iOS (thanks to gatheraled) - (fix) smooth scrolling on iOS (thanks to gatheraled)
- (etc) cookie security measures (thanks to Tom Fitzhenry) - (etc) cookie security measures (thanks to Tom Fitzhenry)
- (etc) restrict access to internal IPs for page crawler (thanks to Omar Kurt)
# v2.5 (2025-03-26) # v2.5 (2025-03-26)

View File

@@ -513,6 +513,10 @@ func (s *Server) handlePageCrawl(c *router.Context) {
}) })
return return
} }
if isInternalFromURL(url) {
log.Printf("attempt to access internal IP %s from %s", url, c.Req.RemoteAddr)
return
}
body, err := worker.GetBody(url) body, err := worker.GetBody(url)
if err != nil { if err != nil {

35
src/server/util.go Normal file
View File

@@ -0,0 +1,35 @@
package server
import (
"net"
"net/url"
"strings"
)
func isInternalFromURL(urlStr string) bool {
parsedURL, err := url.Parse(urlStr)
if err != nil {
return false
}
host := parsedURL.Host
// Handle "host:port" format
if strings.Contains(host, ":") {
host, _, err = net.SplitHostPort(host)
if err != nil {
return false
}
}
if host == "localhost" {
return true
}
ip := net.ParseIP(host)
if ip == nil {
return false
}
return ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast()
}

31
src/server/util_test.go Normal file
View File

@@ -0,0 +1,31 @@
package server
import "testing"
func TestIsInternalFromURL(t *testing.T) {
tests := []struct {
url string
expected bool
}{
{"http://192.168.1.1:8080", true},
{"http://10.0.0.5", true},
{"http://172.16.0.1", true},
{"http://172.31.255.255", true},
{"http://172.32.0.1", false}, // outside private range
{"http://127.0.0.1", true},
{"http://127.0.0.1:7000", true},
{"http://127.0.0.1:7000/secret", true},
{"http://169.254.0.5", true},
{"http://localhost", true}, // resolves to 127.0.0.1
{"http://8.8.8.8", false},
{"http://google.com", false}, // resolves to public IPs
{"invalid-url", false}, // invalid format
{"", false}, // empty string
}
for _, test := range tests {
result := isInternalFromURL(test.url)
if result != test.expected {
t.Errorf("isInternalFromURL(%q) = %v; want %v", test.url, result, test.expected)
}
}
}