Manage traffic at critical connection points with Traffic Policy phases
We're introducing a phase-based approach to our Traffic Policy engine, giving you more granular control over traffic management than we offered before.
This replaces the previous inbound and outbound directions, which are now deprecated, with clearer, phase-specific labels: on_tcp_connect
, on_http_request
, and on_http_response
. These new labels enhance clarity, expanding the ability to manage traffic by configuring actions that will be triggered at precise stages in the connection lifecycle.
Whether you need to deny traffic when a TCP connection is initiated or handle requests after an HTTP request is fully processed, this approach gives you the power to act at exactly the right time.
These changes were driven by the need to give you greater control and clarity in traffic management. Replacing inbound and outbound directions with phase-specific labels enables precise control over handling traffic, such as blocking unwanted connections early at the transport layer or managing TLS termination.
Key updates to Traffic Policy in ngrok
This phase-based approach requires quite a few downstream changes to enable deeper granularity and more flexibility for managing traffic to your APIs and apps.
Phases we support by protocol
Here are the phases we support for HTTP, TLS and TCP:
HTTP endpoints:
on_tcp_connect
on_http_request
replacesinbound
on_http_response
replacesoutbound
TLS endpoints:
on_tcp_connect
replacesinbound
TCP endpoints:
on_tcp_connect
replacesinbound
Actions supported for each phase
Here’s a table that details which actions are supported at each phase:
These changes were driven by several key factors that centered around our user needs and the desire for greater flexibility and clarity in managing traffic flows.
While our existing Traffic Policy engine was strong, we recognized that it didn’t offer the fine-grained control some users required. Specifically, it wasn’t possible to distinguish between different traffic types like TCP and HTTP to take actions earlier in the connection lifecycle. For example, there was no way to intercept or block connections at the transport layer during the TCP connection phase, before application data such as HTTP headers were even transmitted. This lack of control made it difficult for users to enforce important security measures, like blocking traffic at the earliest stage or handling TLS termination and mTLS effectively.
Another reason for this change was to clarify how traffic directions were managed. We noticed that some users misunderstood the purpose of the “outbound
” direction, mistakenly thinking ngrok was acting as a forward proxy. In reality, it was how you manage responses for HTTP traffic. The phase-based approach replaces these directional labels with more intuitive names—on_tcp_connect
, on_http_request
, and on_http_response
—making it clearer where and when specific actions are executed.
This enhancement lays the groundwork for even greater control over traffic management. Looking ahead, we plan to introduce additional phases for different protocols and lifecycle management.
Traffic Policy API and agent configuration file updates
As part of the improvements to our traffic policy engine, we have also made the following changes to enhance clarity and consistency across the platform:
- Changed
--policy-file
flag to--traffic-policy-file
on the CLI - Changed
/policy
endpoint to/traffic_policy
on the edges API - Changed
policy
field totraffic_policy
in the agent configuration file
Additionally, edges no longer require separate inbound
and outbound
objects to define traffic rules. Instead, the system now uses a single configuration field named value, which accepts a stringified Traffic Policy in either JSON or YAML format.
With this update, you can now provide your local YAML or JSON files directly to ngrok without needing to parse them into separate objects. This ensures that your Traffic Policy configurations remain intact in their original format, including any comments within YAML files. This not only simplifies management but also preserves your documentation—critical for understanding the reasoning behind specific policies—every time you update or resubmit configurations. This approach prevents the loss of valuable context and ensures long-term clarity.
Changes to SDKs
In addition to updates to the CLI and Edges, our SDKs have been updated to support the new Traffic Policy changes:
- ngrok-go: The method
WithPolicyString
has been renamed toWithTrafficPolicy
. - ngrok-javascript: The
policy
field has been renamed totraffic_policy
. - ngrok-rust: The
Policy
struct has been renamed toTrafficPolicy
. - ngrok-python: The
policy
field has been renamed totraffic_policy
.
Changes to the Kubernetes Operator
We have made the following changes to the ngrok Kubernetes Operator:
- Traffic Policy configured through the
NgrokTrafficPolicy
CRD now supports new phases. - Traffic Policy generated through Gateway API filters now use new phases.
- Traffic Policy configured through the Gateway API
extensionRef
is translated to the new phases to maintain compatibility with Filters. - The
policy
module in theNgrokModuleSet
has been deprecated.
What can you do with Traffic Policy phases?
Let’s look at what you can do with the on_tcp_connect
phase. You can:
Deny traffic
Before a connection is fully established, you can deny traffic at the TCP layer, preventing the exchange of HTTP headers or data. This significantly reduces the volume of data required for transmission, keeping bandwidth usage and costs minimal while protecting your infrastructure from unnecessary traffic.
For example, if you’re getting overwhelmed with requests from North Korea, you can now deny any requests at the TCP layer:
---
on_tcp_connect:
- name: Block North Korea IP Addresses
expression:
- "conn.Geo.CountryCode in ['KP']"
actions:
- type: deny
Log metadata
You can log details such as connection time, client IP, and connection type to enhance visibility into traffic patterns. This will be useful for compliance and auditing by providing a detailed record of action results and traffic activities, helping ensure that your organization meets regulatory requirements. It also enables easier troubleshooting and security monitoring, allowing you to track unusual or suspicious behavior and respond more effectively to potential threats.
For example, here’s how you can now log incoming client IPs on TCP connection:
---
on_tcp_connection:
- name: Record Client IP
actions:
- type: log
config:
metadata:
client_ip: "${conn.client_ip}"
Restrict IPs
You can block unwanted traffic with our restrict-ips action at the connection phase itself, before it reaches any upstream services. Users attempting to connect from blocked IPs will only experience a failed connection attempt without receiving any feedback or information about why the connection was denied or details about the service itself. This helps maintain security and privacy by not disclosing any information that could be potentially exploited in attacks.
For example you may need to block malicious IPs from accessing your website:
---
on_tcp_connect:
- name: Block Malicious IP Addresses
actions:
- type: restrict-ips
config:
enforce: true
deny:
- "e680:5791:be4c:5739:d959:7b94:6d54:d4b4/128"
These examples highlight the power of applying actions at the on_tcp_connect
phase.
As we continue to enhance the phase-based approach, you’ll unlock even more capabilities with new actions and phases. One of the upcoming features we plan to introduce is the TLS Termination and mTLS (mutual TLS) action. This will allow you to decide when to terminate TLS and enforce security protocols during the on_tcp_connect
phase, giving you greater control and enhanced security.
Deprecation notice: Time to switch to the new format
We have deprecated the inbound
and outbound
phases in Traffic Policy. While we still support existing policies with inbound
and outbound
thanks to how we designed the Traffic Policy engine, they will not be able to take advantage of the new on_tcp_connect
phase until they have been ported to the new format.
We strongly recommend converting your existing policies to the new format to take advantage of these new capabilities. We will eventually sunset the inbound and outbound phases and will provide a timeline with advance notice.
Ready to try the next phase of traffic management on ngrok?
These new and improved phases make policies more intuitive, aligning with real-world scenarios by reflecting distinct stages in the traffic lifecycle. If you’ve never written a Traffic Policy rule before—or haven’t even used ngrok before—start by reading our Traffic Policy docs and other resources on getting the most from Traffic Policy, like request variables and manipulating headers.
You’ll also need a free ngrok account to get your endpoints online with Traffic Policy rules enabled.
Once you’ve configured some Traffic Policies rules with these new phases, let us know what you think by creating an issue or discussion on the ngrok community repo. You can also register for the next session of Office Hours and ask us any questions you may have about phase-based approach to writing policies of your own.