main
go 223 lines 5.03 KB
Raw
1 package policy
2
3 import (
4 "fmt"
5 "net"
6
7 "github.com/gosuda/portal-tunnel/v2/utils"
8 )
9
10 type PortPolicy struct {
11 enabled bool
12 maxLeases int
13 }
14
15 func (p PortPolicy) IsEnabled() bool { return p.enabled }
16 func (p PortPolicy) MaxLeases() int { return p.maxLeases }
17
18 func (p *PortPolicy) Set(enabled bool, maxLeases int) {
19 p.enabled = enabled
20 p.maxLeases = maxLeases
21 }
22
23 type runtimeConfig struct {
24 udp PortPolicy
25 tcpPort PortPolicy
26 trustProxyHeaders bool
27 trustedProxyCIDRs []*net.IPNet
28 }
29
30 func (cfg runtimeConfig) snapshot() runtimeConfig {
31 cfg.trustedProxyCIDRs = utils.CloneSlice(cfg.trustedProxyCIDRs)
32 return cfg
33 }
34
35 type Runtime struct {
36 approver *Approver
37 bpsManager *BPSManager
38 ipFilter *IPFilter
39 config *utils.Snapshot[runtimeConfig]
40 bannedIdentityKeys *utils.Snapshot[map[string]struct{}]
41 }
42
43 func NewRuntime(udpEnabled, tcpPortEnabled bool, trustProxyHeaders bool, rawTrustedProxyCIDRs string) (*Runtime, error) {
44 runtime := &Runtime{
45 approver: NewApprover(),
46 bpsManager: NewBPSManager(),
47 ipFilter: NewIPFilter(),
48 config: utils.NewSnapshot(runtimeConfig{
49 udp: PortPolicy{enabled: udpEnabled},
50 tcpPort: PortPolicy{enabled: tcpPortEnabled},
51 }, runtimeConfig.snapshot),
52 bannedIdentityKeys: utils.NewSnapshot(map[string]struct{}{}, utils.CloneMap[string, struct{}]),
53 }
54 if err := runtime.SetProxyTrust(trustProxyHeaders, rawTrustedProxyCIDRs); err != nil {
55 return nil, err
56 }
57 return runtime, nil
58 }
59
60 func (r *Runtime) Approver() *Approver {
61 return r.approver
62 }
63
64 func (r *Runtime) IPFilter() *IPFilter {
65 return r.ipFilter
66 }
67
68 func (r *Runtime) BPSManager() *BPSManager {
69 return r.bpsManager
70 }
71
72 func (r *Runtime) BanIdentity(key string) {
73 if r == nil || r.bannedIdentityKeys == nil || key == "" {
74 return
75 }
76 r.bannedIdentityKeys.UpdateCopy(func(keys *map[string]struct{}) {
77 if *keys == nil {
78 *keys = make(map[string]struct{})
79 }
80 (*keys)[key] = struct{}{}
81 })
82 }
83
84 func (r *Runtime) UnbanIdentity(key string) {
85 if r == nil || r.bannedIdentityKeys == nil || key == "" {
86 return
87 }
88 r.bannedIdentityKeys.UpdateCopy(func(keys *map[string]struct{}) {
89 delete(*keys, key)
90 })
91 }
92
93 func (r *Runtime) IsIdentityBanned(key string) bool {
94 if r == nil || r.bannedIdentityKeys == nil || key == "" {
95 return false
96 }
97 _, ok := r.bannedIdentityKeys.Load()[key]
98 return ok
99 }
100
101 func (r *Runtime) BannedIdentityKeys() []string {
102 if r == nil || r.bannedIdentityKeys == nil {
103 return nil
104 }
105 keys := r.bannedIdentityKeys.Load()
106 out := make([]string, 0, len(keys))
107 for key := range keys {
108 out = append(out, key)
109 }
110 return out
111 }
112
113 func (r *Runtime) SetBannedIdentityKeys(keys []string) {
114 if r == nil || r.bannedIdentityKeys == nil {
115 return
116 }
117 bannedIdentityKeys := make(map[string]struct{}, len(keys))
118 for _, key := range keys {
119 if key == "" {
120 continue
121 }
122 bannedIdentityKeys[key] = struct{}{}
123 }
124
125 r.bannedIdentityKeys.Store(bannedIdentityKeys)
126 }
127
128 func (r *Runtime) EffectiveApproval(key string) bool {
129 if r.approver == nil || key == "" {
130 return true
131 }
132 if r.approver.Mode() == ModeAuto {
133 return true
134 }
135 return r.approver.IsApproved(key)
136 }
137
138 func (r *Runtime) IsIdentityDenied(key string) bool {
139 if r.approver == nil || key == "" {
140 return false
141 }
142 return r.approver.IsDenied(key)
143 }
144
145 func (r *Runtime) IsIdentityRoutable(key string) bool {
146 if r.IsIdentityBanned(key) || r.IsIdentityDenied(key) {
147 return false
148 }
149 return r.EffectiveApproval(key)
150 }
151
152 func (r *Runtime) SetUDPPolicy(enabled bool, maxLeases int) {
153 if r == nil || r.config == nil {
154 return
155 }
156 r.config.UpdateCopy(func(cfg *runtimeConfig) {
157 cfg.udp.Set(enabled, maxLeases)
158 })
159 }
160
161 func (r *Runtime) IsUDPEnabled() bool {
162 if r == nil || r.config == nil {
163 return false
164 }
165 return r.config.Load().udp.IsEnabled()
166 }
167
168 func (r *Runtime) UDPMaxLeases() int {
169 if r == nil || r.config == nil {
170 return 0
171 }
172 return r.config.Load().udp.MaxLeases()
173 }
174
175 func (r *Runtime) SetTCPPortPolicy(enabled bool, maxLeases int) {
176 if r == nil || r.config == nil {
177 return
178 }
179 r.config.UpdateCopy(func(cfg *runtimeConfig) {
180 cfg.tcpPort.Set(enabled, maxLeases)
181 })
182 }
183
184 func (r *Runtime) SetProxyTrust(trustProxyHeaders bool, rawTrustedProxyCIDRs string) error {
185 if r == nil {
186 return nil
187 }
188 trustedProxyCIDRs, err := utils.ParseCIDRs(rawTrustedProxyCIDRs)
189 if err != nil {
190 return fmt.Errorf("parse trusted proxy cidrs: %w", err)
191 }
192 if r.config == nil {
193 r.config = utils.NewSnapshot(runtimeConfig{}, runtimeConfig.snapshot)
194 }
195 r.config.UpdateCopy(func(cfg *runtimeConfig) {
196 cfg.trustProxyHeaders = trustProxyHeaders
197 cfg.trustedProxyCIDRs = append([]*net.IPNet(nil), trustedProxyCIDRs...)
198 })
199 return nil
200 }
201
202 func (r *Runtime) IsTCPPortEnabled() bool {
203 if r == nil || r.config == nil {
204 return false
205 }
206 return r.config.Load().tcpPort.IsEnabled()
207 }
208
209 func (r *Runtime) TCPPortMaxLeases() int {
210 if r == nil || r.config == nil {
211 return 0
212 }
213 return r.config.Load().tcpPort.MaxLeases()
214 }
215
216 func (r *Runtime) ForgetIdentity(key string) {
217 if r.ipFilter != nil {
218 r.ipFilter.RemoveIdentityIP(key)
219 }
220 if r.bpsManager != nil {
221 r.bpsManager.DeleteIdentityBPS(key)
222 }
223 }