package main import ( "fmt" "strings" ) func renderRuleset(configuration config, publicInterface string) string { smtpObservationWindow := 600 if configuration.SMTPDeny != nil { smtpObservationWindow = configuration.SMTPDeny.MaximumObservationWindow } httpQuarantine := "" if configuration.RelayHTTPQuarantineEnabled { httpQuarantine = fmt.Sprintf(` iifname %q tcp flags syn tcp dport 443 update @recent_https_v4 { ip saddr timeout %dm } delete @http_quarantine_v4 { ip saddr } iifname %q tcp flags syn tcp dport 80 ip saddr @http_quarantine_v4 counter drop iifname %q tcp flags syn tcp dport 80 ip saddr != @recent_https_v4 meter unmatched_http_by_source size %d { ip saddr timeout %dm limit rate over %d/hour burst %d packets } update @http_quarantine_v4 { ip saddr timeout %dm } counter drop`, publicInterface, configuration.RelayHTTPSRecentMinutes, publicInterface, publicInterface, configuration.RelayTrackerMaxSources, configuration.RelayHTTPSRecentMinutes, configuration.RelayUnmatchedHTTPRate, configuration.RelayUnmatchedHTTPBurst, configuration.RelayHTTPQuarantineMinutes) } mailForward := "" mailDNAT := "" mailGuard := "" if configuration.MailRelayAddress != "" { mailForward = fmt.Sprintf(` iifname %q oifname "wg-oci0" ip daddr %s tcp dport { 25, 465, 993 } accept`, publicInterface, configuration.MailRelayAddress) mailDNAT = fmt.Sprintf(` iifname %q tcp dport { 25, 465, 993 } dnat ip to %s`, publicInterface, configuration.MailRelayAddress) mailGuard = fmt.Sprintf(` iifname %q tcp flags syn tcp dport 25 ip saddr @smtp_syn_quarantine_v4 counter name smtp_syn_quarantine_dropped drop iifname %q tcp flags syn tcp dport 25 meter smtp_syn_by_source size %d { ip saddr timeout 1m limit rate over %d/minute burst %d packets } update @smtp_syn_quarantine_v4 { ip saddr timeout %ds } counter name smtp_syn_source_dropped drop iifname %q tcp flags syn tcp dport 25 limit rate over %d/second burst %d packets counter name smtp_syn_aggregate_dropped drop iifname %q tcp dport 25 limit rate over %d/second burst %d packets counter name smtp_packet_aggregate_dropped drop iifname %q tcp flags syn tcp dport { 465, 993 } ip saddr @auth_syn_quarantine_v4 counter name auth_syn_quarantine_dropped drop iifname %q tcp flags syn tcp dport { 465, 993 } meter auth_syn_by_source size %d { ip saddr timeout 1m limit rate over %d/minute burst %d packets } update @auth_syn_quarantine_v4 { ip saddr timeout 10m } counter name auth_syn_source_dropped drop iifname %q tcp flags syn tcp dport { 465, 993 } limit rate over %d/second burst %d packets counter name auth_syn_aggregate_dropped drop iifname %q tcp dport { 465, 993 } limit rate over %d/second burst %d packets counter name auth_packet_aggregate_dropped drop`, publicInterface, publicInterface, configuration.RelayTrackerMaxSources, configuration.RelaySMTPSYNRate, configuration.RelaySMTPSYNBurst, smtpObservationWindow, publicInterface, configuration.RelaySMTPSYNAggregateRate, configuration.RelaySMTPSYNAggregateBurst, publicInterface, configuration.RelaySMTPPacketAggregateRate, configuration.RelaySMTPPacketAggregateBurst, publicInterface, publicInterface, configuration.RelayTrackerMaxSources, configuration.RelayAuthSYNRate, configuration.RelayAuthSYNBurst, publicInterface, configuration.RelayAuthSYNAggregateRate, configuration.RelayAuthSYNAggregateBurst, publicInterface, configuration.RelayAuthPacketAggregateRate, configuration.RelayAuthPacketAggregateBurst) } return strings.TrimSpace(fmt.Sprintf(` flush ruleset table inet oci_l4_relay_web_allow { counter web_allow_denied {} chain ingress { type filter hook prerouting priority raw - 20; policy accept; iifname %q tcp dport { 80, 443, 465, 993 } counter name web_allow_denied drop } } table inet oci_l4_relay_smtp_deny { set denied_v4 { type ipv4_addr flags interval, timeout } counter smtp_denied {} chain ingress { type filter hook prerouting priority raw - 19; policy accept; iifname %q tcp dport 25 ip saddr @denied_v4 counter name smtp_denied drop } } table inet oci_l4_relay { counter web_packet_aggregate_dropped {} counter web_syn_quarantine_dropped {} counter web_syn_source_dropped {} counter web_syn_aggregate_dropped {} counter smtp_packet_aggregate_dropped {} counter smtp_syn_aggregate_dropped {} counter smtp_syn_quarantine_dropped {} counter smtp_syn_source_dropped {} counter auth_packet_aggregate_dropped {} counter auth_syn_aggregate_dropped {} counter auth_syn_quarantine_dropped {} counter auth_syn_source_dropped {} set recent_https_v4 { type ipv4_addr flags dynamic,timeout timeout %dm size %d } set http_quarantine_v4 { type ipv4_addr flags dynamic,timeout timeout %dm size %d } set syn_quarantine_v4 { type ipv4_addr flags dynamic,timeout counter timeout 1m size %d } set smtp_syn_quarantine_v4 { type ipv4_addr flags dynamic,timeout counter timeout %ds size %d } set auth_syn_quarantine_v4 { type ipv4_addr flags dynamic,timeout timeout 10m size %d } chain ingress_guard { type filter hook prerouting priority raw - 10; policy accept;%s iifname %q tcp flags syn tcp dport { 80, 443 } ip saddr @syn_quarantine_v4 counter name web_syn_quarantine_dropped drop iifname %q tcp flags syn tcp dport { 80, 443 } meter web_syn_by_source size %d { ip saddr timeout 1m limit rate over %d/minute burst %d packets } update @syn_quarantine_v4 { ip saddr timeout 1m } counter name web_syn_source_dropped drop iifname %q tcp flags syn tcp dport { 80, 443 } limit rate over %d/second burst %d packets counter name web_syn_aggregate_dropped drop iifname %q tcp dport { 80, 443 } limit rate over %d/second burst %d packets counter name web_packet_aggregate_dropped drop%s } chain input { type filter hook input priority filter; policy drop; iifname "lo" accept ct state established,related accept icmp type 3 icmp code 4 accept iifname %q udp dport %d accept iifname "wg-oci0" tcp dport %d accept } chain output { type filter hook output priority filter; policy drop; oifname "lo" accept ct state established,related accept ip daddr 169.254.169.254 tcp dport 80 accept ip daddr 169.254.169.254 udp dport { 53, 123 } accept ip daddr 169.254.169.254 tcp dport 53 accept udp sport 68 udp dport 67 accept udp sport %d accept tcp dport 443 accept icmp type { 3, 11, 12 } accept } chain forward { type filter hook forward priority filter; policy drop; ct state established,related accept iifname %q oifname "wg-oci0" ip daddr %s tcp dport { 80, 443 } accept%s iifname "wg-oci0" oifname %q ct state established,related accept } chain prerouting { type nat hook prerouting priority dstnat; policy accept; iifname %q tcp dport { 80, 443 } dnat ip to %s%s } } `, publicInterface, publicInterface, configuration.RelayHTTPSRecentMinutes, configuration.RelayTrackerMaxSources, configuration.RelayHTTPQuarantineMinutes, configuration.RelayTrackerMaxSources, configuration.RelayTrackerMaxSources, smtpObservationWindow, configuration.RelayTrackerMaxSources, configuration.RelayTrackerMaxSources, httpQuarantine, publicInterface, publicInterface, configuration.RelayTrackerMaxSources, configuration.RelayWebSYNRate, configuration.RelayWebSYNBurst, publicInterface, configuration.RelayWebSYNAggregateRate, configuration.RelayWebSYNAggregateBurst, publicInterface, configuration.RelayWebPacketAggregateRate, configuration.RelayWebPacketAggregateBurst, mailGuard, publicInterface, configuration.WireGuardListenPort, configuration.RelayMetricsPort, configuration.WireGuardListenPort, publicInterface, configuration.GatewayRelayAddress, mailForward, publicInterface, publicInterface, configuration.GatewayRelayAddress, mailDNAT)) + "\n" }