Adds a container label match_sni_to_host which allow setting the matchSNIToHost configuration via a label, similar to the http2_origin label (code copied and adapted)

This commit is contained in:
Nick Rosier 2026-03-19 08:57:55 +01:00
parent ab871eef34
commit 0b0c60fc4d
No known key found for this signature in database
3 changed files with 21 additions and 0 deletions

View file

@ -160,6 +160,7 @@ def process_container_start(container_obj):
no_tls_verify_label = get_label(labels, "no_tls_verify", "false").lower() in ["true", "1", "t", "yes"]
http2_origin_label = get_label(labels, "http2_origin", "false").lower() in ["true", "1", "t", "yes"]
disable_chunked_encoding_label = get_label(labels, "disable_chunked_encoding", "false").lower() in ["true", "1", "t", "yes"]
match_sni_to_host_label = get_label(labels, "match_sni_to_host", "false").lower() in ["true", "1", "t", "yes"]
if hostname_label and service_label:
if is_valid_hostname(hostname_label) and is_valid_service(service_label):
@ -171,6 +172,7 @@ def process_container_start(container_obj):
"http_host_header": default_http_host_header_label.strip() if default_http_host_header_label else None,
"http2_origin": http2_origin_label,
"disable_chunked_encoding": disable_chunked_encoding_label,
"match_sni_to_host": match_sni_to_host_label,
"access_group": default_access_group,
"access_policy_type": default_access_policy_type_label,
"access_app_name": default_access_app_name_label,
@ -203,6 +205,8 @@ def process_container_start(container_obj):
http2_origin_indexed = http2_origin_indexed_val.lower() in ["true", "1", "t", "yes"]
disable_chunked_encoding_indexed_val = get_label(labels, f"{index}.disable_chunked_encoding", str(disable_chunked_encoding_label).lower())
disable_chunked_encoding_indexed = disable_chunked_encoding_indexed_val.lower() in ["true", "1", "t", "yes"]
match_sni_to_host_indexed_val = get_label(labels, f"{index}.match_sni_to_host", str(match_sni_to_host_label).lower())
match_sni_to_host_indexed = match_sni_to_host_indexed_val.lower() in ["true", "1", "t", "yes"]
access_groups_indexed = get_label(labels, f"{index}.access.groups")
raw_access_group_indexed = get_label(labels, f"{index}.access.group") if not access_groups_indexed else None
@ -255,6 +259,7 @@ def process_container_start(container_obj):
"http_host_header": http_host_header_indexed_val.strip() if http_host_header_indexed_val else None,
"http2_origin": http2_origin_indexed,
"disable_chunked_encoding": disable_chunked_encoding_indexed,
"match_sni_to_host": match_sni_to_host_indexed,
"access_group": access_group_indexed,
"access_policy_type": access_policy_type_indexed,
"access_app_name": access_app_name_indexed,
@ -298,6 +303,7 @@ def process_container_start(container_obj):
http_host_header_from_item = config_item.get("http_host_header")
http2_origin_from_item = config_item.get("http2_origin", False)
disable_chunked_encoding_from_item = config_item.get("disable_chunked_encoding", False)
match_sni_to_host_from_item = config_item.get("match_sni_to_host", False)
target_zone_id = None
detected_zone_name = zone_name_from_item
@ -368,6 +374,9 @@ def process_container_start(container_obj):
if existing_rule.get("disable_chunked_encoding") != disable_chunked_encoding_from_item:
existing_rule["disable_chunked_encoding"] = disable_chunked_encoding_from_item
rule_data_changed = True
if existing_rule.get("match_sni_to_host") != match_sni_to_host_from_item:
existing_rule["match_sni_to_host"] = match_sni_to_host_from_item
rule_data_changed = True
existing_rule["source"] = "docker"
if master_tunnel_id and existing_rule.get("tunnel_id") != master_tunnel_id:
@ -405,6 +414,7 @@ def process_container_start(container_obj):
"http_host_header": http_host_header_from_item,
"http2_origin": http2_origin_from_item,
"disable_chunked_encoding": disable_chunked_encoding_from_item,
"match_sni_to_host": match_sni_to_host_from_item,
"access_app_id": None,
"access_policy_type": None,
"access_app_config_hash": None,

View file

@ -18,6 +18,7 @@ These labels control the fundamental routing and service definition for a contai
| `dockflare.httpHostHeader` | Overrides the `Host` header sent from `cloudflared` to your origin service. | `dockflare.httpHostHeader=custom-host.internal` |
| `dockflare.http2_origin` | If set to `true`, enables HTTP/2 protocol for the connection between `cloudflared` and your origin service. Required for gRPC services. Only applies to HTTP/HTTPS services. | `dockflare.http2_origin=true` |
| `dockflare.disable_chunked_encoding` | If set to `true`, disables chunked transfer encoding over HTTP/1.1. Useful for WSGI servers (Flask, Django, FastAPI) and other origins that don't properly support chunked requests. Only applies to HTTP/HTTPS services. | `dockflare.disable_chunked_encoding=true` |
| `dockflare.match_sni_to_host` | If set to `true`, Cloudflare automatically sets the Server Name Indication (SNI) during the TLS handshake to match the incoming request's hostname. | `dockflare.match_sni_to_host=true` |
> **Tip:** Starting with DockFlare v3.0, you can skip `dockflare.zonename` for most workloads. The master detects the correct Cloudflare zone by matching the hostname suffix and only falls back to the configured default zone when it cannot find a match. Provide the label when you intentionally want to place a record in a different zone.

View file

@ -816,6 +816,7 @@ def process_agent_container_start(payload, agent_id):
no_tls_verify_label = get_label(labels, "no_tls_verify", "false").lower() in ["true", "1", "t", "yes"]
http2_origin_label = get_label(labels, "http2_origin", "false").lower() in ["true", "1", "t", "yes"]
disable_chunked_encoding_label = get_label(labels, "disable_chunked_encoding", "false").lower() in ["true", "1", "t", "yes"]
match_sni_to_host_label = get_label(labels, "match_sni_to_host", "false").lower() in ["true", "1", "t", "yes"]
if hostname_label and service_label:
if is_valid_hostname(hostname_label) and is_valid_service(service_label):
@ -829,6 +830,7 @@ def process_agent_container_start(payload, agent_id):
"http_host_header": default_http_host_header_label.strip() if default_http_host_header_label else None,
"http2_origin": http2_origin_label,
"disable_chunked_encoding": disable_chunked_encoding_label,
"match_sni_to_host": match_sni_to_host_label,
"access_group": default_access_group,
"access_policy_type": default_access_policy_type_label,
"access_app_name": default_access_app_name_label,
@ -861,6 +863,8 @@ def process_agent_container_start(payload, agent_id):
http2_origin_indexed = http2_origin_indexed_val.lower() in ["true", "1", "t", "yes"]
disable_chunked_encoding_indexed_val = get_label(labels, f"{index}.disable_chunked_encoding", str(disable_chunked_encoding_label).lower())
disable_chunked_encoding_indexed = disable_chunked_encoding_indexed_val.lower() in ["true", "1", "t", "yes"]
match_sni_to_host_indexed_val = get_label(labels, f"{index}.match_sni_to_host", str(match_sni_to_host_label).lower())
match_sni_to_host_indexed = match_sni_to_host_indexed_val.lower() in ["true", "1", "t", "yes"]
access_groups_indexed = get_label(labels, f"{index}.access.groups")
raw_access_group_indexed = get_label(labels, f"{index}.access.group") if not access_groups_indexed else None
@ -915,6 +919,7 @@ def process_agent_container_start(payload, agent_id):
"http_host_header": http_host_header_indexed_val.strip() if http_host_header_indexed_val else None,
"http2_origin": http2_origin_indexed,
"disable_chunked_encoding": disable_chunked_encoding_indexed,
"match_sni_to_host": match_sni_to_host_indexed,
"access_group": access_group_indexed,
"access_policy_type": access_policy_type_indexed,
"access_app_name": access_app_name_indexed,
@ -955,6 +960,7 @@ def process_agent_container_start(payload, agent_id):
http_host_header_from_item = config_item.get("http_host_header")
http2_origin_from_item = config_item.get("http2_origin", False)
disable_chunked_encoding_from_item = config_item.get("disable_chunked_encoding", False)
match_sni_to_host_from_item = config_item.get("match_sni_to_host", False)
target_zone_id = None
if zone_name_from_item:
@ -1007,6 +1013,9 @@ def process_agent_container_start(payload, agent_id):
if existing_rule.get("disable_chunked_encoding") != disable_chunked_encoding_from_item:
existing_rule["disable_chunked_encoding"] = disable_chunked_encoding_from_item
rule_data_changed = True
if existing_rule.get("match_sni_to_host") != match_sni_to_host_from_item:
existing_rule["match_sni_to_host"] = match_sni_to_host_from_item
rule_data_changed = True
if existing_rule.get("tunnel_name") != assigned_tunnel_name:
existing_rule["tunnel_name"] = assigned_tunnel_name
rule_data_changed = True
@ -1045,6 +1054,7 @@ def process_agent_container_start(payload, agent_id):
"http_host_header": config_item.get("http_host_header"),
"http2_origin": http2_origin_from_item,
"disable_chunked_encoding": disable_chunked_encoding_from_item,
"match_sni_to_host": match_sni_to_host_from_item,
"access_app_id": None,
"access_policy_type": None,
"access_app_config_hash": None,