ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
216
services/oci-l4-relay-guest/config.go
Normal file
216
services/oci-l4-relay-guest/config.go
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
Admission admissionConfig `json:"admission"`
|
||||
AdmissionHelper string `json:"admission_helper"`
|
||||
GatewayRelayAddress string `json:"gateway_relay_address"`
|
||||
HomeWireGuardPublicKey string `json:"home_wireguard_public_key"`
|
||||
LogIngestHostname string `json:"log_ingest_hostname"`
|
||||
LogIngestSecretOCID string `json:"log_ingest_secret_ocid"`
|
||||
MailRelayAddress string `json:"mail_relay_address,omitempty"`
|
||||
MonitoringSourceIPv4 []string `json:"monitoring_source_ipv4"`
|
||||
PublicKeySecretOCID string `json:"public_key_secret_ocid"`
|
||||
RateLimitMbit int `json:"rate_limit_mbit"`
|
||||
RelayHTTPQuarantineEnabled bool `json:"relay_http_quarantine_enabled"`
|
||||
RelayHTTPQuarantineMinutes int `json:"relay_http_quarantine_minutes"`
|
||||
RelayHTTPSRecentMinutes int `json:"relay_https_recent_minutes"`
|
||||
RelayMetricsPort int `json:"relay_metrics_port"`
|
||||
RelayAuthPacketAggregateBurst int `json:"relay_auth_packet_aggregate_burst"`
|
||||
RelayAuthPacketAggregateRate int `json:"relay_auth_packet_aggregate_rate_per_second"`
|
||||
RelayAuthSYNAggregateBurst int `json:"relay_auth_syn_aggregate_burst"`
|
||||
RelayAuthSYNAggregateRate int `json:"relay_auth_syn_aggregate_rate_per_second"`
|
||||
RelayAuthSYNBurst int `json:"relay_auth_syn_burst"`
|
||||
RelayAuthSYNRate int `json:"relay_auth_syn_rate_per_minute"`
|
||||
RelaySMTPPacketAggregateBurst int `json:"relay_smtp_packet_aggregate_burst"`
|
||||
RelaySMTPPacketAggregateRate int `json:"relay_smtp_packet_aggregate_rate_per_second"`
|
||||
RelaySMTPSYNAggregateBurst int `json:"relay_smtp_syn_aggregate_burst"`
|
||||
RelaySMTPSYNAggregateRate int `json:"relay_smtp_syn_aggregate_rate_per_second"`
|
||||
RelaySMTPSYNBurst int `json:"relay_smtp_syn_burst"`
|
||||
RelaySMTPSYNRate int `json:"relay_smtp_syn_rate_per_minute"`
|
||||
RelayTrackerMaxSources int `json:"relay_tracker_max_sources"`
|
||||
RelayTunnelAddress string `json:"relay_tunnel_address"`
|
||||
RelayTunnelMTU int `json:"relay_tunnel_mtu"`
|
||||
RelayUnmatchedHTTPBurst int `json:"relay_unmatched_http_burst"`
|
||||
RelayUnmatchedHTTPRate int `json:"relay_unmatched_http_rate_per_hour"`
|
||||
RelayWebPacketAggregateBurst int `json:"relay_web_packet_aggregate_burst"`
|
||||
RelayWebPacketAggregateRate int `json:"relay_web_packet_aggregate_rate_per_second"`
|
||||
RelayWebSYNAggregateBurst int `json:"relay_web_syn_aggregate_burst"`
|
||||
RelayWebSYNAggregateRate int `json:"relay_web_syn_aggregate_rate_per_second"`
|
||||
RelayWebSYNBurst int `json:"relay_web_syn_burst"`
|
||||
RelayWebSYNRate int `json:"relay_web_syn_rate_per_minute"`
|
||||
SMTPDeny *smtpDenyConfig `json:"smtp_deny,omitempty"`
|
||||
SMTPDenyHelper string `json:"smtp_deny_helper,omitempty"`
|
||||
WireGuardListenPort int `json:"wireguard_listen_port"`
|
||||
WireGuardSeedSecretOCID string `json:"wireguard_seed_secret_ocid"`
|
||||
mailConfigurationError string
|
||||
}
|
||||
|
||||
type admissionConfig struct {
|
||||
Bucket string `json:"bucket"`
|
||||
MaximumAddresses uint64 `json:"maximum_addresses"`
|
||||
MinimumAddresses uint64 `json:"minimum_addresses"`
|
||||
MinimumIntervals int `json:"minimum_intervals"`
|
||||
Namespace string `json:"namespace"`
|
||||
Object string `json:"object"`
|
||||
}
|
||||
|
||||
type smtpDenyConfig struct {
|
||||
Bucket string `json:"bucket"`
|
||||
MaximumAddresses uint64 `json:"maximum_addresses"`
|
||||
MaximumIntervals int `json:"maximum_intervals"`
|
||||
MaximumLifetimeSeconds int `json:"maximum_lifetime_seconds"`
|
||||
MaximumObservationWindow int `json:"maximum_observation_window_seconds"`
|
||||
MinimumObservations uint64 `json:"minimum_observations"`
|
||||
Namespace string `json:"namespace"`
|
||||
Object string `json:"object"`
|
||||
}
|
||||
|
||||
func loadConfig(path string) (config, error) {
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return config{}, err
|
||||
}
|
||||
var value config
|
||||
decoder := json.NewDecoder(bytes.NewReader(contents))
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(&value); err != nil {
|
||||
return config{}, err
|
||||
}
|
||||
if err := value.validate(); err != nil {
|
||||
return config{}, err
|
||||
}
|
||||
if err := value.validateMail(); err != nil {
|
||||
value.MailRelayAddress = ""
|
||||
value.SMTPDeny = nil
|
||||
value.SMTPDenyHelper = ""
|
||||
value.mailConfigurationError = err.Error()
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (value config) validate() error {
|
||||
required := map[string]string{
|
||||
"admission.bucket": value.Admission.Bucket,
|
||||
"admission.namespace": value.Admission.Namespace,
|
||||
"admission.object": value.Admission.Object,
|
||||
"admission_helper": value.AdmissionHelper,
|
||||
"gateway_relay_address": value.GatewayRelayAddress,
|
||||
"home_wireguard_public_key": value.HomeWireGuardPublicKey,
|
||||
"log_ingest_hostname": value.LogIngestHostname,
|
||||
"log_ingest_secret_ocid": value.LogIngestSecretOCID,
|
||||
"public_key_secret_ocid": value.PublicKeySecretOCID,
|
||||
"relay_tunnel_address": value.RelayTunnelAddress,
|
||||
"wireguard_seed_secret_ocid": value.WireGuardSeedSecretOCID,
|
||||
}
|
||||
for name, candidate := range required {
|
||||
if candidate == "" {
|
||||
return fmt.Errorf("%s is required", name)
|
||||
}
|
||||
}
|
||||
positive := map[string]int{
|
||||
"admission.minimum_intervals": value.Admission.MinimumIntervals,
|
||||
"rate_limit_mbit": value.RateLimitMbit,
|
||||
"relay_http_quarantine_minutes": value.RelayHTTPQuarantineMinutes,
|
||||
"relay_https_recent_minutes": value.RelayHTTPSRecentMinutes,
|
||||
"relay_metrics_port": value.RelayMetricsPort,
|
||||
"relay_tracker_max_sources": value.RelayTrackerMaxSources,
|
||||
"relay_tunnel_mtu": value.RelayTunnelMTU,
|
||||
"relay_unmatched_http_burst": value.RelayUnmatchedHTTPBurst,
|
||||
"relay_unmatched_http_rate_per_hour": value.RelayUnmatchedHTTPRate,
|
||||
"relay_web_packet_aggregate_burst": value.RelayWebPacketAggregateBurst,
|
||||
"relay_web_packet_aggregate_rate_per_second": value.RelayWebPacketAggregateRate,
|
||||
"relay_web_syn_aggregate_burst": value.RelayWebSYNAggregateBurst,
|
||||
"relay_web_syn_aggregate_rate_per_second": value.RelayWebSYNAggregateRate,
|
||||
"relay_web_syn_burst": value.RelayWebSYNBurst,
|
||||
"relay_web_syn_rate_per_minute": value.RelayWebSYNRate,
|
||||
"wireguard_listen_port": value.WireGuardListenPort,
|
||||
}
|
||||
for name, candidate := range positive {
|
||||
if candidate <= 0 {
|
||||
return fmt.Errorf("%s must be positive", name)
|
||||
}
|
||||
}
|
||||
if value.RelayMetricsPort > 65535 {
|
||||
return errors.New("relay_metrics_port must not exceed 65535")
|
||||
}
|
||||
if value.Admission.MinimumAddresses == 0 || value.Admission.MaximumAddresses < value.Admission.MinimumAddresses {
|
||||
return errors.New("admission address bounds are invalid")
|
||||
}
|
||||
if len(value.MonitoringSourceIPv4) < 3 {
|
||||
return errors.New("at least three monitoring source IPv4 addresses are required")
|
||||
}
|
||||
seen := make(map[netip.Addr]bool, len(value.MonitoringSourceIPv4))
|
||||
for _, candidate := range value.MonitoringSourceIPv4 {
|
||||
address, err := netip.ParseAddr(candidate)
|
||||
if err != nil || !address.Is4() || address.String() != candidate || seen[address] {
|
||||
return fmt.Errorf("invalid or duplicate monitoring source IPv4 address %q", candidate)
|
||||
}
|
||||
seen[address] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (value config) validateMail() error {
|
||||
if value.MailRelayAddress == "" && value.SMTPDeny == nil && value.SMTPDenyHelper == "" {
|
||||
return nil
|
||||
}
|
||||
address, err := netip.ParseAddr(value.MailRelayAddress)
|
||||
if err != nil || !address.Is4() || address.String() != value.MailRelayAddress || value.MailRelayAddress == value.GatewayRelayAddress {
|
||||
return errors.New("mail_relay_address must be a distinct canonical IPv4 address")
|
||||
}
|
||||
if value.SMTPDeny == nil {
|
||||
return errors.New("smtp_deny is required when mail relay is configured")
|
||||
}
|
||||
required := map[string]string{
|
||||
"smtp_deny.bucket": value.SMTPDeny.Bucket,
|
||||
"smtp_deny.namespace": value.SMTPDeny.Namespace,
|
||||
"smtp_deny.object": value.SMTPDeny.Object,
|
||||
"smtp_deny_helper": value.SMTPDenyHelper,
|
||||
}
|
||||
for name, candidate := range required {
|
||||
if candidate == "" {
|
||||
return fmt.Errorf("%s is required", name)
|
||||
}
|
||||
}
|
||||
if value.SMTPDeny.MinimumObservations == 0 ||
|
||||
value.SMTPDeny.MaximumAddresses == 0 ||
|
||||
value.SMTPDeny.MaximumIntervals <= 0 ||
|
||||
value.SMTPDeny.MaximumLifetimeSeconds <= 0 ||
|
||||
value.SMTPDeny.MaximumObservationWindow <= 0 ||
|
||||
value.SMTPDeny.MaximumObservationWindow > value.SMTPDeny.MaximumLifetimeSeconds {
|
||||
return errors.New("smtp_deny policy bounds are invalid")
|
||||
}
|
||||
positive := map[string]int{
|
||||
"relay_auth_packet_aggregate_burst": value.RelayAuthPacketAggregateBurst,
|
||||
"relay_auth_packet_aggregate_rate_per_second": value.RelayAuthPacketAggregateRate,
|
||||
"relay_auth_syn_aggregate_burst": value.RelayAuthSYNAggregateBurst,
|
||||
"relay_auth_syn_aggregate_rate_per_second": value.RelayAuthSYNAggregateRate,
|
||||
"relay_auth_syn_burst": value.RelayAuthSYNBurst,
|
||||
"relay_auth_syn_rate_per_minute": value.RelayAuthSYNRate,
|
||||
"relay_smtp_packet_aggregate_burst": value.RelaySMTPPacketAggregateBurst,
|
||||
"relay_smtp_packet_aggregate_rate_per_second": value.RelaySMTPPacketAggregateRate,
|
||||
"relay_smtp_syn_aggregate_burst": value.RelaySMTPSYNAggregateBurst,
|
||||
"relay_smtp_syn_aggregate_rate_per_second": value.RelaySMTPSYNAggregateRate,
|
||||
"relay_smtp_syn_burst": value.RelaySMTPSYNBurst,
|
||||
"relay_smtp_syn_rate_per_minute": value.RelaySMTPSYNRate,
|
||||
}
|
||||
for name, candidate := range positive {
|
||||
if candidate <= 0 {
|
||||
return fmt.Errorf("%s must be positive", name)
|
||||
}
|
||||
}
|
||||
if value.RelayAuthPacketAggregateBurst < value.RelayAuthPacketAggregateRate ||
|
||||
value.RelaySMTPPacketAggregateBurst < value.RelaySMTPPacketAggregateRate {
|
||||
return errors.New("mail packet aggregate bursts must cover at least one second")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in a new issue