feat(security): Implemented more security information
This commit is contained in:
@@ -6,29 +6,47 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"warpbox/lib/security"
|
||||
)
|
||||
|
||||
func clientIP(ctx *gin.Context) string {
|
||||
func (app *App) clientIP(ctx *gin.Context) string {
|
||||
if ctx == nil || ctx.Request == nil {
|
||||
return ""
|
||||
}
|
||||
remoteIP := remoteAddrIP(ctx.Request)
|
||||
|
||||
// Only trust forwarding headers when remote hop looks like local/internal proxy.
|
||||
if isPrivateOrLoopback(remoteIP) {
|
||||
for _, candidate := range headerIPs(ctx.Request.Header) {
|
||||
if isPublicIP(candidate) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
candidates := headerIPs(ctx.Request.Header)
|
||||
if len(candidates) > 0 {
|
||||
return candidates[0]
|
||||
trusted, err := security.ParseCIDRList(app.config.TrustedProxyCIDRs)
|
||||
if err != nil {
|
||||
return remoteIP
|
||||
}
|
||||
if !remoteIsTrusted(remoteIP, trusted) {
|
||||
return remoteIP
|
||||
}
|
||||
for _, candidate := range headerIPs(ctx.Request.Header) {
|
||||
if isPublicIP(candidate) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
candidates := headerIPs(ctx.Request.Header)
|
||||
if len(candidates) > 0 {
|
||||
return candidates[0]
|
||||
}
|
||||
return remoteIP
|
||||
}
|
||||
|
||||
func remoteIsTrusted(remoteIP string, trusted []net.IPNet) bool {
|
||||
ip := net.ParseIP(strings.TrimSpace(remoteIP))
|
||||
if ip == nil {
|
||||
return false
|
||||
}
|
||||
for _, prefix := range trusted {
|
||||
if prefix.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func headerIPs(header http.Header) []string {
|
||||
keys := []string{
|
||||
"X-Forwarded-For",
|
||||
|
||||
Reference in New Issue
Block a user