mirror of
https://github.com/dcarrillo/whatismyip.git
synced 2024-12-22 12:08:00 +00:00
Remove headers set by a trusted proxy from outputs
This commit is contained in:
parent
7c70abf07f
commit
1ee7256506
@ -3,9 +3,11 @@ package httputils
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dcarrillo/whatismyip/internal/setting"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +34,17 @@ func HeadersToSortedString(headers http.Header) string {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHeadersWithoutTrustedHeaders return a http.Heade object with the original headers except trusted headers
|
||||||
|
func GetHeadersWithoutTrustedHeaders(ctx *gin.Context) http.Header {
|
||||||
|
h := ctx.Request.Header
|
||||||
|
|
||||||
|
for _, k := range []string{setting.App.TrustedHeader, setting.App.TrustedPortHeader} {
|
||||||
|
delete(h, textproto.CanonicalMIMEHeaderKey(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
// GetLogFormatter returns our custom log format
|
// GetLogFormatter returns our custom log format
|
||||||
func GetLogFormatter(param gin.LogFormatterParams) string {
|
func GetLogFormatter(param gin.LogFormatterParams) string {
|
||||||
return fmt.Sprintf("%s - [%s] \"%s %s %s\" %d %d %d %s \"%s\" \"%s\" \"%s\"\n",
|
return fmt.Sprintf("%s - [%s] \"%s %s %s\" %d %d %d %s \"%s\" \"%s\" \"%s\"\n",
|
||||||
|
@ -70,15 +70,17 @@ func Setup(args []string) (output string, err error) {
|
|||||||
)
|
)
|
||||||
flags.StringVar(&App.TLSCrtPath, "tls-crt", "", "When using TLS, path to certificate file")
|
flags.StringVar(&App.TLSCrtPath, "tls-crt", "", "When using TLS, path to certificate file")
|
||||||
flags.StringVar(&App.TLSKeyPath, "tls-key", "", "When using TLS, path to private key file")
|
flags.StringVar(&App.TLSKeyPath, "tls-key", "", "When using TLS, path to private key file")
|
||||||
flags.StringVar(&App.TrustedHeader,
|
flags.StringVar(
|
||||||
|
&App.TrustedHeader,
|
||||||
"trusted-header",
|
"trusted-header",
|
||||||
"",
|
"",
|
||||||
"Trusted request header for remote IP (e.g. X-Real-IP)",
|
"Trusted request header for remote IP (e.g. X-Real-IP). When using this feature if -trusted-port-header is not set the client port is shown as 'unknown'",
|
||||||
)
|
)
|
||||||
flags.StringVar(&App.TrustedPortHeader,
|
flags.StringVar(
|
||||||
|
&App.TrustedPortHeader,
|
||||||
"trusted-port-header",
|
"trusted-port-header",
|
||||||
"",
|
"",
|
||||||
"Trusted request header for remote client port (e.g. X-Real-Port)",
|
"Trusted request header for remote client port (e.g. X-Real-Port). When this parameter is set -trusted-header becomes mandatory",
|
||||||
)
|
)
|
||||||
flags.BoolVar(&App.version, "version", false, "Output version information and exit")
|
flags.BoolVar(&App.version, "version", false, "Output version information and exit")
|
||||||
flags.BoolVar(
|
flags.BoolVar(
|
||||||
|
@ -79,8 +79,8 @@ func getAllAsString(ctx *gin.Context) {
|
|||||||
output += geoASNRecordToString(record) + "\n"
|
output += geoASNRecordToString(record) + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
h := ctx.Request.Header
|
h := httputils.GetHeadersWithoutTrustedHeaders(ctx)
|
||||||
h["Host"] = []string{ctx.Request.Host}
|
h.Set("Host", ctx.Request.Host)
|
||||||
output += httputils.HeadersToSortedString(h)
|
output += httputils.HeadersToSortedString(h)
|
||||||
|
|
||||||
ctx.String(http.StatusOK, output)
|
ctx.String(http.StatusOK, output)
|
||||||
@ -113,6 +113,6 @@ func jsonOutput(ctx *gin.Context) JSONResponse {
|
|||||||
ASN: asnRecord.AutonomousSystemNumber,
|
ASN: asnRecord.AutonomousSystemNumber,
|
||||||
ASNOrganization: asnRecord.AutonomousSystemOrganization,
|
ASNOrganization: asnRecord.AutonomousSystemOrganization,
|
||||||
Host: ctx.Request.Host,
|
Host: ctx.Request.Host,
|
||||||
Headers: ctx.Request.Header,
|
Headers: httputils.GetHeadersWithoutTrustedHeaders(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,9 +102,6 @@ func TestClientPort(t *testing.T) {
|
|||||||
params []string
|
params []string
|
||||||
headers map[string][]string
|
headers map[string][]string
|
||||||
}
|
}
|
||||||
type expected struct {
|
|
||||||
body string
|
|
||||||
}
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args args
|
args args
|
||||||
@ -249,8 +246,6 @@ ASN Organization:
|
|||||||
|
|
||||||
Header1: one
|
Header1: one
|
||||||
Host: test
|
Host: test
|
||||||
X-Real-Ip: 81.2.69.192
|
|
||||||
X-Real-Port: 1001
|
|
||||||
`
|
`
|
||||||
_, _ = setting.Setup(
|
_, _ = setting.Setup(
|
||||||
[]string{
|
[]string{
|
||||||
|
@ -10,15 +10,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func getHeadersAsSortedString(ctx *gin.Context) {
|
func getHeadersAsSortedString(ctx *gin.Context) {
|
||||||
h := ctx.Request.Header
|
h := httputils.GetHeadersWithoutTrustedHeaders(ctx)
|
||||||
h["Host"] = []string{ctx.Request.Host}
|
h.Set("Host", ctx.Request.Host)
|
||||||
|
|
||||||
ctx.String(http.StatusOK, httputils.HeadersToSortedString(h))
|
ctx.String(http.StatusOK, httputils.HeadersToSortedString(h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHeaderAsString(ctx *gin.Context) {
|
func getHeaderAsString(ctx *gin.Context) {
|
||||||
|
headers := httputils.GetHeadersWithoutTrustedHeaders(ctx)
|
||||||
|
|
||||||
h := ctx.Params.ByName("header")
|
h := ctx.Params.ByName("header")
|
||||||
if v := ctx.GetHeader(h); v != "" {
|
if v := headers.Get(ctx.Params.ByName("header")); v != "" {
|
||||||
ctx.String(http.StatusOK, template.HTMLEscapeString(v))
|
ctx.String(http.StatusOK, template.HTMLEscapeString(v))
|
||||||
} else if strings.ToLower(h) == "host" {
|
} else if strings.ToLower(h) == "host" {
|
||||||
ctx.String(http.StatusOK, template.HTMLEscapeString(ctx.Request.Host))
|
ctx.String(http.StatusOK, template.HTMLEscapeString(ctx.Request.Host))
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/dcarrillo/whatismyip/internal/setting"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,13 +27,20 @@ Header2: value22
|
|||||||
Header3: value3
|
Header3: value3
|
||||||
Host:
|
Host:
|
||||||
`
|
`
|
||||||
|
_, _ = setting.Setup([]string{
|
||||||
|
"-geoip2-city", "city",
|
||||||
|
"-geoip2-asn", "asn",
|
||||||
|
"-trusted-header", trustedHeader,
|
||||||
|
"-trusted-port-header", trustedPortHeader,
|
||||||
|
})
|
||||||
req, _ := http.NewRequest("GET", "/headers", nil)
|
req, _ := http.NewRequest("GET", "/headers", nil)
|
||||||
req.Header = map[string][]string{
|
req.Header = map[string][]string{
|
||||||
"Header1": {"value1"},
|
"Header1": {"value1"},
|
||||||
"Header2": {"value21", "value22"},
|
"Header2": {"value21", "value22"},
|
||||||
"Header3": {"value3"},
|
"Header3": {"value3"},
|
||||||
}
|
}
|
||||||
|
req.Header.Set(trustedHeader, "1.1.1.1")
|
||||||
|
req.Header.Set(trustedPortHeader, "1025")
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
app.ServeHTTP(w, req)
|
app.ServeHTTP(w, req)
|
||||||
|
@ -34,8 +34,8 @@ var (
|
|||||||
text: "text/plain; charset=utf-8",
|
text: "text/plain; charset=utf-8",
|
||||||
json: "application/json; charset=utf-8",
|
json: "application/json; charset=utf-8",
|
||||||
}
|
}
|
||||||
jsonIPv4 = `{"client_port":"1001","ip":"81.2.69.192","ip_version":4,"country":"United Kingdom","country_code":"GB","city":"London","latitude":51.5142,"longitude":-0.0931,"postal_code":"","time_zone":"Europe/London","asn":0,"asn_organization":"","host":"test","headers":{"X-Real-Ip":["81.2.69.192"], "X-Real-Port":["1001"]}}`
|
jsonIPv4 = `{"client_port":"1001","ip":"81.2.69.192","ip_version":4,"country":"United Kingdom","country_code":"GB","city":"London","latitude":51.5142,"longitude":-0.0931,"postal_code":"","time_zone":"Europe/London","asn":0,"asn_organization":"","host":"test", "headers": {}}`
|
||||||
jsonIPv6 = `{"asn":3352, "asn_organization":"TELEFONICA DE ESPANA", "city":"", "client_port":"1001", "country":"", "country_code":"", "headers":{"X-Real-Ip":["2a02:9000::1"], "X-Real-Port":["1001"]}, "host":"test", "ip":"2a02:9000::1", "ip_version":6, "latitude":0, "longitude":0, "postal_code":"", "time_zone":""}`
|
jsonIPv6 = `{"asn":3352, "asn_organization":"TELEFONICA DE ESPANA", "city":"", "client_port":"1001", "country":"", "country_code":"", "host":"test", "ip":"2a02:9000::1", "ip_version":6, "latitude":0, "longitude":0, "postal_code":"", "time_zone":"", "headers": {}}`
|
||||||
)
|
)
|
||||||
|
|
||||||
const trustedHeader = "X-Real-IP"
|
const trustedHeader = "X-Real-IP"
|
||||||
|
Loading…
Reference in New Issue
Block a user