main
go 163 lines 5.31 KB
Raw
1 package types
2
3 import (
4 "encoding/json"
5 "strings"
6 "time"
7 )
8
9 const (
10 IdentityKeySeparator = ":"
11 RelayIdentityFilename = "identity.json"
12 RelayPolicyFilename = "policy.json"
13 )
14
15 type Identity struct {
16 Name string `json:"name,omitempty"`
17 Address string `json:"address,omitempty"`
18 PublicKey string `json:"-"`
19 PrivateKey string `json:"-"`
20 Mnemonic string `json:"-"`
21 DerivationPath string `json:"-"`
22 TokenSecret string `json:"-"`
23 }
24
25 func (i Identity) Copy() Identity {
26 return Identity{
27 Name: i.Name,
28 Address: i.Address,
29 PublicKey: i.PublicKey,
30 PrivateKey: i.PrivateKey,
31 Mnemonic: i.Mnemonic,
32 DerivationPath: i.DerivationPath,
33 TokenSecret: i.TokenSecret,
34 }
35 }
36
37 type RelayIdentity struct {
38 Identity
39 WireGuardPublicKey string `json:"-"`
40 WireGuardPrivateKey string `json:"-"`
41 EncryptedClientHelloSeed string `json:"-"`
42 }
43
44 func (i RelayIdentity) Copy() RelayIdentity {
45 return RelayIdentity{
46 Identity: i.Identity.Copy(),
47 WireGuardPublicKey: i.WireGuardPublicKey,
48 WireGuardPrivateKey: i.WireGuardPrivateKey,
49 EncryptedClientHelloSeed: i.EncryptedClientHelloSeed,
50 }
51 }
52
53 func (i Identity) Key() string {
54 name := strings.TrimSpace(strings.ToLower(i.Name))
55 address := strings.TrimSpace(strings.ToLower(i.Address))
56 if name == "" && address == "" {
57 return ""
58 }
59 return name + IdentityKeySeparator + address
60 }
61
62 type LeaseMetadata struct {
63 Description string `json:"description,omitempty"`
64 Owner string `json:"owner,omitempty"`
65 Thumbnail string `json:"thumbnail,omitempty"`
66 Tags []string `json:"tags,omitempty"`
67 Hide bool `json:"hide,omitempty"`
68 }
69
70 func (m LeaseMetadata) Copy() LeaseMetadata {
71 return LeaseMetadata{
72 Description: m.Description,
73 Owner: m.Owner,
74 Thumbnail: m.Thumbnail,
75 Tags: append([]string(nil), m.Tags...),
76 Hide: m.Hide,
77 }
78 }
79
80 type Lease struct {
81 Name string `json:"name,omitempty"`
82 ExpiresAt time.Time `json:"expires_at"`
83 FirstSeenAt time.Time `json:"first_seen_at"`
84 LastSeenAt time.Time `json:"last_seen_at"`
85 Hostname string `json:"hostname"`
86 UDPEnabled bool `json:"udp_enabled,omitempty"`
87 TCPEnabled bool `json:"tcp_enabled,omitempty"`
88 TCPAddr string `json:"tcp_addr,omitempty"`
89 Metadata LeaseMetadata `json:"metadata"`
90 Ready int `json:"ready"`
91 }
92
93 type PolicyLease struct {
94 Lease
95 IdentityKey string `json:"identity_key,omitempty"`
96 Address string `json:"address,omitempty"`
97 BPS int64 `json:"bps"`
98 ClientIP string `json:"client_ip"`
99 ReportedIP string `json:"reported_ip,omitempty"`
100 IsApproved bool `json:"is_approved"`
101 IsBanned bool `json:"is_banned"`
102 IsDenied bool `json:"is_denied"`
103 IsIPBanned bool `json:"is_ip_banned"`
104 }
105
106 type RelayDescriptor struct {
107 Address string `json:"address"`
108 Version string `json:"version"`
109 IssuedAt time.Time `json:"issued_at"`
110 ExpiresAt time.Time `json:"expires_at"`
111 APIHTTPSAddr string `json:"api_https_addr"`
112 WireGuardPublicKey string `json:"wireguard_public_key,omitempty"`
113 WireGuardPort int `json:"wireguard_port,omitempty"`
114 SupportsOverlay bool `json:"supports_overlay,omitempty"`
115 SupportsUDP bool `json:"supports_udp,omitempty"`
116 SupportsTCP bool `json:"supports_tcp,omitempty"`
117 ActiveConnections int64 `json:"active_connections,omitempty"`
118 TCPBPS float64 `json:"tcp_bps,omitempty"`
119 Signature string `json:"signature,omitempty"`
120 }
121
122 func (desc RelayDescriptor) HasOverlayPeer() bool {
123 return desc.SupportsOverlay &&
124 strings.TrimSpace(desc.WireGuardPublicKey) != "" &&
125 desc.WireGuardPort > 0 &&
126 desc.WireGuardPort <= 65535
127 }
128
129 // CanonicalBytes returns the deterministic byte representation of a relay
130 // descriptor used for signing and signature verification.
131 //
132 // The encoding is JSON over a fixed struct schema (no maps, no omitempty),
133 // which guarantees field order and presence regardless of input variation.
134 func CanonicalBytes(desc RelayDescriptor) ([]byte, error) {
135 canonical := struct {
136 Address string `json:"address"`
137 Version string `json:"version"`
138 IssuedAtUnixNano int64 `json:"issued_at_unix_nano"`
139 ExpiresAtUnixNano int64 `json:"expires_at_unix_nano"`
140 APIHTTPSAddr string `json:"api_https_addr"`
141 WireGuardPublicKey string `json:"wireguard_public_key"`
142 WireGuardPort int `json:"wireguard_port"`
143 SupportsOverlay bool `json:"supports_overlay"`
144 SupportsUDP bool `json:"supports_udp"`
145 SupportsTCP bool `json:"supports_tcp"`
146 ActiveConnections int64 `json:"active_connections"`
147 TCPBPS float64 `json:"tcp_bps"`
148 }{
149 Address: desc.Address,
150 Version: desc.Version,
151 IssuedAtUnixNano: desc.IssuedAt.UTC().UnixNano(),
152 ExpiresAtUnixNano: desc.ExpiresAt.UTC().UnixNano(),
153 APIHTTPSAddr: desc.APIHTTPSAddr,
154 WireGuardPublicKey: desc.WireGuardPublicKey,
155 WireGuardPort: desc.WireGuardPort,
156 SupportsOverlay: desc.SupportsOverlay,
157 SupportsUDP: desc.SupportsUDP,
158 SupportsTCP: desc.SupportsTCP,
159 ActiveConnections: desc.ActiveConnections,
160 TCPBPS: desc.TCPBPS,
161 }
162 return json.Marshal(canonical)
163 }