Files
Wormhole/internal/auth/ip.go
T
rose_cat707 0d84b07f68
CI / docker (push) Successful in 1m58s
feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。
Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 17:52:43 +08:00

56 lines
1.4 KiB
Go

package auth
import (
"net"
"net/http"
"strings"
)
// DirectRemoteIP returns the direct TCP peer address, ignoring X-Forwarded-For.
// Use for security decisions (login rate limit, IP rules, resource auth).
func DirectRemoteIP(r *http.Request) string {
return HostOnly(r.RemoteAddr)
}
// AddrHost extracts the host portion from a net.Addr string (host:port or [host]:port).
func AddrHost(addr net.Addr) string {
if addr == nil {
return ""
}
return HostOnly(addr.String())
}
// HostOnly strips the port from an address string.
func HostOnly(addr string) string {
if addr == "" {
return ""
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
return strings.Trim(addr, "[]")
}
return host
}
// ExtractRemoteIP returns the client IP, honoring X-Forwarded-For when present.
// Use only when forwarding visitor IP to upstream backends behind a trusted proxy.
func ExtractRemoteIP(r *http.Request) string {
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
parts := strings.Split(xff, ",")
return strings.TrimSpace(parts[0])
}
if xri := r.Header.Get("X-Real-IP"); xri != "" {
return strings.TrimSpace(xri)
}
return DirectRemoteIP(r)
}
// SafeRedirectPath validates a post-login redirect path (relative only).
func SafeRedirectPath(raw string) string {
raw = strings.TrimSpace(raw)
if raw == "" || !strings.HasPrefix(raw, "/") || strings.HasPrefix(raw, "//") {
return "/"
}
return raw
}