gitea

Development moved to Codeberg

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  100. 100
  101. 101
  102. 102
  103. 103
  104. 104
  105. 105
  106. 106
  107. 107
  108. 108
  109. 109
  110. 110
  111. 111
  112. 112
  113. 113
  114. 114
  115. 115
// Copyright 2020 Lauris BH. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package proxy

import (
	"net"
)

// ForwardedHeadersOptions represents options for forwarded header middleware
type ForwardedHeadersOptions struct {
	// ForwardLimit limits the number of entries in the headers that will be processed.
	// The default value is 1. Set to 0 to disable the limit.
	ForwardLimit int
	// TrustingAllProxies option sets to trust all proxies.
	TrustingAllProxies bool
	// KnownProxies represents addresses of trusted proxies.
	TrustedProxies []net.IP
	// TrustedNetworks represents addresses of trusted networks.
	TrustedNetworks []*net.IPNet
}

var defaultOptions = &ForwardedHeadersOptions{
	ForwardLimit: 1,
	TrustedProxies: []net.IP{
		net.IPv4(127, 0, 0, 1),
	},
}

// NewForwardedHeadersOptions creates new middleware options
func NewForwardedHeadersOptions() *ForwardedHeadersOptions {
	return &ForwardedHeadersOptions{
		ForwardLimit:    defaultOptions.ForwardLimit,
		TrustedProxies:  defaultOptions.TrustedProxies,
		TrustedNetworks: defaultOptions.TrustedNetworks,
	}
}

// WithForwardLimit sets number of entries to be processed
func (opts *ForwardedHeadersOptions) WithForwardLimit(limit int) *ForwardedHeadersOptions {
	opts.ForwardLimit = limit
	return opts
}

// TrustAllProxies sets to trust all proxies
func (opts *ForwardedHeadersOptions) TrustAllProxies() *ForwardedHeadersOptions {
	opts.TrustingAllProxies = true
	return opts
}

// ClearTrustedProxies clears trusted proxy list
func (opts *ForwardedHeadersOptions) ClearTrustedProxies() *ForwardedHeadersOptions {
	opts.TrustingAllProxies = false
	opts.TrustedProxies = make([]net.IP, 0)
	return opts
}

// AddTrustedProxy adds proxy IP to trusted proxy list
func (opts *ForwardedHeadersOptions) AddTrustedProxy(ip string) *ForwardedHeadersOptions {
	// Special option to trust all proxies if IP address is set as wildcard
	if ip == "*" {
		opts.TrustingAllProxies = true
		return opts
	}

	ipaddr := net.ParseIP(ip)
	if ipaddr == nil {
		return opts
	}

	opts.TrustedProxies = append(opts.TrustedProxies, ipaddr)
	return opts
}

// ClearTrustedNetworks clears trusted network list
func (opts *ForwardedHeadersOptions) ClearTrustedNetworks() *ForwardedHeadersOptions {
	opts.TrustedNetworks = make([]*net.IPNet, 0)
	return opts
}

// AddTrustedNetwork adds network to trusted network list
func (opts *ForwardedHeadersOptions) AddTrustedNetwork(cidr string) *ForwardedHeadersOptions {
	_, netmask, err := net.ParseCIDR(cidr)
	if err != nil || netmask == nil {
		return opts
	}

	opts.TrustedNetworks = append(opts.TrustedNetworks, netmask)
	return opts
}

func (opts *ForwardedHeadersOptions) isTrustedProxy(ip net.IP) bool {
	if opts.TrustingAllProxies {
		return true
	}

	if ip == nil {
		return false
	}

	for _, tip := range opts.TrustedProxies {
		if tip.Equal(ip) {
			return true
		}
	}

	for _, tnet := range opts.TrustedNetworks {
		if tnet.Contains(ip) {
			return true
		}
	}

	return false
}