Solo para leer y verificar. No puedes copiar, usar, modificar ni redistribuir este código. Aviso completo en la página principal.
tunnel/policy.go
| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | _ "embed" |
| 5 | "encoding/json" |
| 6 | "fmt" |
| 7 | "regexp" |
| 8 | "strings" |
| 9 | "time" |
| 10 | ) |
| 11 | |
| 12 | // policy.json is the byte-identical copy of contracts/policy.json that `the contract generator's sync` writes (the Go module cannot read |
| 13 | // contracts/ at runtime). Every number, window and pattern of the node comes from it: nothing here types one again. |
| 14 | // |
| 15 | //go:embed policy.json |
| 16 | var policyJSON []byte |
| 17 | |
| 18 | // Policy is the part of the ALL 2.0 policy table the node reads. |
| 19 | type Policy struct { |
| 20 | Protocol struct { |
| 21 | Version int `json:"version"` |
| 22 | ALPN string `json:"alpn"` |
| 23 | LineMaxBytes int `json:"line_max_bytes"` |
| 24 | OpenLineMaxBytes int `json:"open_line_max_bytes"` |
| 25 | StatementLineMaxBytes int `json:"statement_line_max_bytes"` |
| 26 | JWTMaxBytes int `json:"jwt_max_bytes"` |
| 27 | FirstLineTimeoutS int `json:"first_line_timeout_s"` |
| 28 | AttachTimeoutS int `json:"attach_timeout_s"` |
| 29 | HintMaxAddresses int `json:"hint_max_addresses"` |
| 30 | ProofHTM string `json:"proof_htm"` |
| 31 | ProofHTUPath string `json:"proof_htu_path"` |
| 32 | SourceClasses []string `json:"source_classes"` |
| 33 | CloseReasons []string `json:"close_reasons"` |
| 34 | ErrorCodes []string `json:"error_codes"` |
| 35 | } `json:"protocol"` |
| 36 | Timing struct { |
| 37 | PingIntervalS int `json:"ping_interval_s"` |
| 38 | DeadPeerS int `json:"dead_peer_s"` |
| 39 | StreamIdleS int `json:"stream_idle_s"` |
| 40 | StreamMaxAgeS int `json:"stream_max_age_s"` |
| 41 | HalfCloseS int `json:"half_close_s"` |
| 42 | BackoffMinS int `json:"backoff_min_s"` |
| 43 | RenewBeforeValidUntilS int `json:"renew_before_valid_until_s"` |
| 44 | BackoffMaxS int `json:"backoff_max_s"` |
| 45 | DrainQuietS int `json:"drain_quiet_s"` |
| 46 | FeedPollS int `json:"feed_poll_s"` |
| 47 | FeedApplyDeadlineS int `json:"feed_apply_deadline_s"` |
| 48 | } `json:"timing"` |
| 49 | Authorization struct { |
| 50 | SessionTTLS int `json:"session_ttl_s"` |
| 51 | ProofTTLS int `json:"proof_ttl_s"` |
| 52 | NodeSkewS int `json:"node_skew_s"` |
| 53 | NodeSkewMaxS int `json:"node_skew_max_s"` |
| 54 | AuthorizeMaxConcur int `json:"authorize_max_concurrent"` |
| 55 | NodeAssertionTTLS int `json:"node_assertion_ttl_s"` |
| 56 | GracePaidS int `json:"grace_paid_s"` |
| 57 | } `json:"authorization"` |
| 58 | Identity struct { |
| 59 | Issuer string `json:"issuer"` |
| 60 | AudTunnel string `json:"aud_tunnel"` |
| 61 | AudNodeAssert string `json:"aud_node_assertion"` |
| 62 | FQDNRegex string `json:"fqdn_regex"` |
| 63 | FQDNMaxLength int `json:"fqdn_max_length"` |
| 64 | LabelRegex string `json:"label_regex"` |
| 65 | DeviceIDRegex string `json:"device_id_regex"` |
| 66 | StreamIDRegex string `json:"stream_id_regex"` |
| 67 | AttachSecretRE string `json:"attach_secret_regex"` |
| 68 | NonceRegex string `json:"nonce_regex"` |
| 69 | JTIRegex string `json:"jti_regex"` |
| 70 | KIDRegex string `json:"kid_regex"` |
| 71 | } `json:"identity"` |
| 72 | JWKS struct { |
| 73 | CacheS int `json:"cache_s"` |
| 74 | MaxKeys int `json:"max_keys"` |
| 75 | StaleFailClosedS int `json:"stale_fail_closed_s"` |
| 76 | } `json:"jwks"` |
| 77 | Enums struct { |
| 78 | FeedEventType []string `json:"feed_event_type"` |
| 79 | } `json:"enums"` |
| 80 | NodeLimits struct { |
| 81 | ClientHelloDeadlineS int `json:"client_hello_deadline_s"` |
| 82 | PerIPConcurrent int `json:"per_ip_concurrent"` |
| 83 | PerIPNewPerS int `json:"per_ip_new_per_s"` |
| 84 | IPv6PrefixBits int `json:"ipv6_prefix_bits"` |
| 85 | LabelStreamsMax int `json:"label_streams_max"` |
| 86 | LabelAnonSlice int `json:"label_anon_slice"` |
| 87 | LabelHintSlice int `json:"label_hint_slice"` |
| 88 | HintTTLS int `json:"hint_ttl_s"` |
| 89 | GlobalStreamsMax int `json:"global_streams_max"` |
| 90 | OpenAIReservedPct int `json:"openai_reserved_pct"` |
| 91 | OpenAIPrefixRefreshS int `json:"openai_prefix_refresh_s"` |
| 92 | OpenAIPrefixMax int `json:"openai_prefix_max"` |
| 93 | OpenAIPrefixMinV4Bits int `json:"openai_prefix_min_v4_bits"` |
| 94 | OpenAIPrefixMinV6Bits int `json:"openai_prefix_min_v6_bits"` |
| 95 | OpenAIPrefixBodyMaxBytes int `json:"openai_prefix_body_max_bytes"` |
| 96 | OpenAIPerIPFactor int `json:"openai_per_ip_factor"` |
| 97 | DevicePerIPFactor int `json:"device_per_ip_factor"` |
| 98 | IPTableMax int `json:"ip_table_max"` |
| 99 | UnknownSNIPerIP int `json:"unknown_sni_per_ip"` |
| 100 | UnknownSNIWindowS int `json:"unknown_sni_window_s"` |
| 101 | UnknownSNIBanS int `json:"unknown_sni_ban_s"` |
| 102 | LabelNewPerS int `json:"label_new_per_s"` |
| 103 | LabelNewBurst int `json:"label_new_burst"` |
| 104 | HintAddressesPerLabel int `json:"hint_addresses_per_label"` |
| 105 | TCPKeepaliveS int `json:"tcp_keepalive_s"` |
| 106 | MaxUnauthenticatedControl int `json:"max_unauthenticated_control"` |
| 107 | } `json:"node_limits"` |
| 108 | Gated struct { |
| 109 | BytesPerDay int64 `json:"bytes_per_day"` |
| 110 | StreamsPerDay int `json:"streams_per_day"` |
| 111 | } `json:"gated"` |
| 112 | } |
| 113 | |
| 114 | // policyData is the parsed table, read once. The file is embedded, so a bad one is a build error found by the first test, never a runtime state. |
| 115 | var policyData = func() *Policy { |
| 116 | var p Policy |
| 117 | if err := json.Unmarshal(policyJSON, &p); err != nil { |
| 118 | panic("tunnel/policy.json: " + err.Error()) |
| 119 | } |
| 120 | return &p |
| 121 | }() |
| 122 | |
| 123 | // secs turns a policy value in seconds into a Duration. |
| 124 | func secs(n int) time.Duration { return time.Duration(n) * time.Second } |
| 125 | |
| 126 | // anchored compiles one of the policy's ^...$ patterns (RE2: `$` is the end of the text, so a trailing newline never matches). |
| 127 | func anchored(pattern string) *regexp.Regexp { |
| 128 | if !strings.HasPrefix(pattern, "^") || !strings.HasSuffix(pattern, "$") { |
| 129 | panic(fmt.Sprintf("policy patterns are anchored: %s", pattern)) |
| 130 | } |
| 131 | return regexp.MustCompile(pattern) |
| 132 | } |
| 133 | |
| 134 | // The patterns of the contracts, compiled from the policy and never written again. |
| 135 | var ( |
| 136 | reLabel = anchored(policyData.Identity.LabelRegex) |
| 137 | reFQDN = anchored(policyData.Identity.FQDNRegex) |
| 138 | reDeviceID = anchored(policyData.Identity.DeviceIDRegex) |
| 139 | reStreamID = anchored(policyData.Identity.StreamIDRegex) |
| 140 | reSecret = anchored(policyData.Identity.AttachSecretRE) |
| 141 | reNonce = anchored(policyData.Identity.NonceRegex) |
| 142 | reJTI = anchored(policyData.Identity.JTIRegex) |
| 143 | reKID = anchored(policyData.Identity.KIDRegex) |
| 144 | ) |
| 145 | |
| 146 | // inList reports whether s is one of the words. |
| 147 | func inList(words []string, s string) bool { |
| 148 | for _, w := range words { |
| 149 | if w == s { |
| 150 | return true |
| 151 | } |
| 152 | } |
| 153 | return false |
| 154 | } |
| 155 | |
| 156 | // validFQDN is the contracts' device host: exactly one label under a zone, at most the policy length. |
| 157 | func validFQDN(s string) bool { |
| 158 | return len(s) <= policyData.Identity.FQDNMaxLength && reFQDN.MatchString(s) |
| 159 | } |