| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- package sub
- import (
- "net"
- "net/netip"
- "strings"
- "sync"
- "github.com/gin-gonic/gin"
- "github.com/mhsanaei/3x-ui/v3/internal/logger"
- "github.com/mhsanaei/3x-ui/v3/internal/web/service"
- )
- var warnSuppressedForwardedOnce sync.Once
- var forwardedHeaderNames = [...]string{"X-Forwarded-Host", "X-Forwarded-Proto", "X-Real-IP"}
- func (s *SubService) forwardedHeadersTrusted(c *gin.Context) (trusted bool) {
- if !hasForwardedHeaders(c) {
- return true
- }
- trusted = true
- defer func() {
- _ = recover()
- }()
- configured, err := s.settingService.GetTrustedProxyCIDRs()
- if err != nil {
- return true
- }
- configured = strings.TrimSpace(configured)
- if configured == "" || configured == service.DefaultTrustedProxyCIDRs {
- return true
- }
- return remoteAddrInCIDRs(c.Request.RemoteAddr, configured)
- }
- func hasForwardedHeaders(c *gin.Context) bool {
- for _, name := range forwardedHeaderNames {
- if c.GetHeader(name) != "" {
- return true
- }
- }
- return false
- }
- func warnSuppressedForwardedHeaders(c *gin.Context) {
- present := make([]string, 0, 3)
- for _, name := range forwardedHeaderNames {
- if c.GetHeader(name) != "" {
- present = append(present, name)
- }
- }
- if len(present) == 0 {
- return
- }
- headers := strings.Join(present, ", ")
- logger.Debugf("sub: ignoring %s from %s, which is outside trustedProxyCIDRs", headers, c.Request.RemoteAddr)
- warnSuppressedForwardedOnce.Do(func() {
- logger.Warningf("sub: ignoring %s from %s because it is outside trustedProxyCIDRs; subscription URLs will use the request host. Add the proxy to that setting, or set subURI, if the generated links look wrong.", headers, c.Request.RemoteAddr)
- })
- }
- func remoteAddrInCIDRs(remoteAddr, cidrs string) bool {
- host := remoteAddr
- if h, _, err := net.SplitHostPort(remoteAddr); err == nil {
- host = h
- }
- addr, err := netip.ParseAddr(strings.TrimSpace(host))
- if err != nil {
- return false
- }
- addr = addr.Unmap()
- for value := range strings.SplitSeq(cidrs, ",") {
- value = strings.TrimSpace(value)
- if value == "" {
- continue
- }
- if prefix, err := netip.ParsePrefix(value); err == nil {
- if prefix.Contains(addr) {
- return true
- }
- continue
- }
- if proxyIP, err := netip.ParseAddr(value); err == nil && proxyIP.Unmap() == addr.Unmap() {
- return true
- }
- }
- return false
- }
|