Add feature.network.incoming.raw_tcp_ports#4209
Add feature.network.incoming.raw_tcp_ports#4209fergusean wants to merge 2 commits intometalbear-co:mainfrom
feature.network.incoming.raw_tcp_ports#4209Conversation
|
Thank you for your contribution!
Can you share a minimal reproducible example? We're not aware of such bug, and that should be handled before we add more explicit config, if needed. |
Base SetupTab 1create test deployment & service in cluster ( tail logs Tab 2create a pod from which to test connections ( connect to expected result: plus you should see Introduce mirrordTab 2expected result: Tab 3connect to expected result: However, you'll notice that neither the cluster listener in tab 1, nor the local listener in tab 2 show a connection. Now type something and hit enter. While the timeout in |
then we can discuss how to handle the connection that are server first byte by default before implementing? |
Summary
Introduces a new
feature.network.incoming.raw_tcp_portsconfig option — a list of ports that should be stolen as raw TCP, bypassing HTTP detection and TLS handling entirely.By default, mirrord runs HTTP detection on every stolen port by reading the first bytes the client sends. For server-first protocols (SMTP, FTP, custom binary protocols, etc.) the client sends nothing after connecting — it waits for the server to speak first. Because the detection read blocks until data arrives, and data never arrives, these connections hang indefinitely and are never forwarded to the local application.
Ports listed in
raw_tcp_portsskip detection and are forwarded to the local application immediately as raw byte streams.What changed
Protocol (
mirrord-protocol→ 1.27.0)StealType::AllRawTcp(Port)— a new steal subscription variant that signals the agent to skip HTTP detection for a port.STEAL_RAW_TCP_VERSION(>=1.27.0) for capability negotiation.StealType::get_port()now covers the new variant.BlockedActiondisplay updated to includeAllRawTcp.Config (
mirrord-config)raw_tcp_ports: Option<Vec<u16>>toIncomingConfig.raw_tcp_portswhen an HTTP filter applies to all ports (i.e.,http_filter.portsis unset), and rejects any port that appears in bothraw_tcp_portsandhttp_filter.ports.raw_tcp_portswarning (the field is silently ignored in mirror mode).raw_tcp_ports_count.Layer (
mirrord-layer-lib)IncomingModecarries theraw_tcp_portsset.IncomingMode::subscription()emitsStealType::AllRawTcpfor ports in the set, taking priority over HTTP filter logic.intproxy (
mirrord-intproxy)PortSubscriptionExt::requests_raw_tcp()identifies raw TCP subscriptions.agent_subscribe()downgradesAllRawTcptoAllwhen talking to an older agent (with a warning), preserving backward compatibility.SubscriptionsManager::layer_subscribed()rejects a second subscription on the same port if it requests a different mode, returningPortAlreadyStolen.Agent (
mirrord-agent)IncomingPortModeenum (Detect|RawTcp) tracked per port inPortState.MaybeHttp::accept_raw_tcp()wraps a redirected connection without running detection.RedirectorTaskusesport_modeto branch:RawTcpports skip the detectionselect!entirely.StealHandle::steal()now takes amodeargument.steal/api.rsmapsStealType::AllRawTcp→IncomingPortMode::RawTcp; all other steal types →IncomingPortMode::Detect.Tests
mirror_detection_survives_later_raw_tcp_steal/raw_tcp_steal_mode_survives_later_mirror— verify that port-wide mode is fixed by the first subscriber.rejects_mode_change_for_existing_subscription— intproxy correctly rejects a second layer that tries to change the mode.raw_tcp_ports_subscribe_raw_tcp— layer-level integration test confirmingAllRawTcpis sent to the agent for ports inraw_tcp_ports.Quality Checklist:
documentation)