From cf9dac20253cc975f01120dae1987616e061edaf Mon Sep 17 00:00:00 2001 From: Ryan Faircloth Date: Thu, 17 Mar 2022 15:59:58 -0400 Subject: [PATCH] feat: Support Loadbalancer proxy proto for TCP/TLS --- docs/experiments.md | 2 +- docs/lb.md | 13 +++++++++++++ mkdocs.yml | 3 ++- .../conf.d/sources/source_syslog/plugin.jinja | 16 ++++++++++++++++ .../etc/conf.d/sources/source_syslog/plugin.py | 12 ++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 docs/lb.md diff --git a/docs/experiments.md b/docs/experiments.md index 3ec434284b..54d1c78172 100644 --- a/docs/experiments.md +++ b/docs/experiments.md @@ -12,4 +12,4 @@ generic linux events for example without this feature the "vendor product by hos - Benefit: Less config interaction - Risk: Potential disk I/O usage (space, iops) Potential reduction in throughput when a high proportion of events are incomplete. - Risk: missidentification due to load balancers and relay sources. - +* `SC4S_SOURCE_PROXYCONNECT=yes` for TCP and TLS connection expect "PROXY CONNECT" to provide the original client IP in SNAT load balancing \ No newline at end of file diff --git a/docs/lb.md b/docs/lb.md new file mode 100644 index 0000000000..319e92d21d --- /dev/null +++ b/docs/lb.md @@ -0,0 +1,13 @@ +# A word about load balancers + +Customers often "require" the use of load balancers incorrectly attempting to meet a business requirement for availability. In general load balancers are not recommended with the exception of of a narrow use case where the Syslog Server must be exposed to untrusted clients on the internet such as Palo Alto Cortex. + +## Considerations + +* UDP MUST only pass a load balancer using DNAT. Source IP must be preserved. Note in this configuration a Load Balancer becomes a new single point of failure +* TCP/TLS May use a DNAT configuration OR SNAT with "PROXY" Protocol enabled `SC4S_SOURCE_PROXYCONNECT=yes` (Experimental) +* TCP/TLS load balancers do not consider the weight of individual connection load is frequently biased to one instance all members in a single resource pool should be vertically scaled to accomidate the full workload. + +## Alternatives + +The best deployment model for high availability is a Microk8s based deployment with MetalLB in BGP mode. This model uses a special class of load balancer that is implemented as destination network translation. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index d4e89a6c7c..00bf381e01 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -24,6 +24,8 @@ theme: nav: - Home: "index.md" + - "Architectural Considerations": "architecture.md" + - Load Balancers: "lb.md" - Getting Started: - "Read First": "gettingstarted/index.md" - "Podman + systemd": "gettingstarted/podman-systemd-general.md" @@ -33,7 +35,6 @@ nav: - "Docker Desktop + Compose (MacOS)": "gettingstarted/docker-compose-MacOS.md" - "Bring your own Envionment": "gettingstarted/byoe-rhel8.md" - "Quickstart Guide": "gettingstarted/quickstart_guide.md" - - Architectural Considerations: "architecture.md" - Configuration: "configuration.md" - Development: "developing/index.md" - Destinations: "destinations.md" diff --git a/package/etc/conf.d/sources/source_syslog/plugin.jinja b/package/etc/conf.d/sources/source_syslog/plugin.jinja index a70e401563..7e256a3f0a 100644 --- a/package/etc/conf.d/sources/source_syslog/plugin.jinja +++ b/package/etc/conf.d/sources/source_syslog/plugin.jinja @@ -30,7 +30,11 @@ source s_{{ port_id }} { {%- if port != "disabled" %} {%- for i in range(1,port_tcp_sockets+1) %} network ( + {%- if use_proxy_connect == True %} + transport("proxied-tcp") + {%- else %} transport("tcp") + {%- endif %} so-reuseport(1) port({{ port }}) persist-name("{{ port_id }}_tcp_{{ port }}_{{ i }}") @@ -54,7 +58,11 @@ source s_{{ port_id }} { {%- if port != "disabled" and use_tls %} {%- for i in range(1,port_tls_sockets+1) %} network ( + {%- if use_proxy_connect == True %} + transport("proxied-tls") + {%- else %} transport("tls") + {%- endif %} so-reuseport(1) port({{ port }}) persist-name("{{ port_id }}_tls_{{ port }}_{{ i }}") @@ -279,7 +287,11 @@ source s_{{ port_id }} { {%- if port != "disabled" %} {%- for i in range(1,port_6587_sockets+1) %} syslog ( + {%- if use_proxy_connect == True %} + transport("proxied-tcp") + {%- else %} transport("tcp") + {%- endif %} so-reuseport(1) port({{ port }}) persist-name("{{ port_id }}_6587_{{ port }}_{{ i }}") @@ -303,7 +315,11 @@ source s_{{ port_id }} { {%- if port != "disabled" and use_tls %} {%- for i in range(1,port_5425_sockets+1) %} syslog ( + {%- if use_proxy_connect == True %} + transport("proxied-tls") + {%- else %} transport("tls") + {%- endif %} so-reuseport(1) port({{ port }}) persist-name("{{ port_id }}_5425_{{ port }}_{{ i }}") diff --git a/package/etc/conf.d/sources/source_syslog/plugin.py b/package/etc/conf.d/sources/source_syslog/plugin.py index 2cc2800313..9498c1ed0e 100755 --- a/package/etc/conf.d/sources/source_syslog/plugin.py +++ b/package/etc/conf.d/sources/source_syslog/plugin.py @@ -84,6 +84,17 @@ cert_file = "server.pem" key_file = "server.key" +# +if os.getenv(f"SC4S_SOURCE_PROXYCONNECT", "no").lower() in [ + "true", + "1", + "t", + "y", + "yes", +]: + use_proxy_connect = True +else: + use_proxy_connect = False for port_id in ports.split(","): outputText = tm.render( @@ -94,6 +105,7 @@ use_namecache=use_namecache, use_vpscache=use_vpscache, use_tls=use_tls, + use_proxy_connect=use_proxy_connect, tls_dir=os.getenv(f"SC4S_TLS", "/etc/syslog-ng/tls"), cert_file=cert_file, key_file=key_file,