Traffic Proxy
This chapter covers some aspects related to the
service traffic-proxy <id> tool, which allows you to configure one or
multiple SSL Proxy instances in OSDx.
The traffic-proxy service can be used to intercept and proxy SSL traffic. This feature can be used to play the role of man-in-the-middle, allowing the inspection of encrypted traffic.
Configuration
Each instance can be bound to a different local port, where the incoming traffic, originated on the client side, is received, mangled and diverted to the server. Upon receiving the packets back from the server, the traffic proxy re-encrypts and sends them to their original destination.
This is the syntax to create a service traffic-proxy <id> instance:
set service traffic-proxy <NAME> [ ... ]
Where <NAME> represents the name of the instance.
When you configure a new instance, you need to specify at least the following parameters:
mode: SSL proxy operating mode. It accepts the following values:httporhttps: to decode plain or secure HTTP connections.pop3,pop3s,smtporsmtps: to decode plain or secure POP3 or SMTP connections.sslortcp: to not decode connections, but treat the decrypted content as an opaque stream of bytes.autossl: to not decode connections, but work as protocol-independent STARTTLS.
x509 ca-certandx509 ca-key: path to PEM CA certificate and key.port: local port that will be used to intercept traffic.
Warning
Make sure to select the appropriate mode. If you need to decrypt multiple
kinds of protocols, you can always configure several instances. Take into
account that if you configure, for example, https or ssl mode and the
service intercepts plain http traffic, it will reject the connection
sending an abort response.
By default, the generated traffic is not VRF-aware, which means that the main
VRF will be used. The instances can also be configured to use a specific VRF,
using the local-vrf field.
Intercepting and analyzing traffic
In order to intercept traffic, you need to create a traffic policy <txt>
and configure it to proxy the traffic to the aforementioned local port. Then,
you should attach that policy to an interface or configure it globally. Further
information about traffic policies can be found at the
Traffic Policy chapter.
Each instance can also be bound to a traffic queue <txt>. Although this
is not required, it’s very useful to configure a traffic queue to be able to
analyze the decrypted traffic; for example, using a firewall instance. Further
information about traffic queues can be found at the
Traffic Queue chapter.
Simple example
Imagine that you want to configure the traffic-proxy service to intercept and decrypt SSL traffic destined to another server; e.g., HTTPs traffic.
Preparing the device
First, we need to have, at least, a valid x509 certificate and private key. We can generate them using an OSDx device:
Example:
admin@DUT0$ pki generate private-key running://test.key rsa
Generated private key at 'running://test.key'
admin@DUT0$ pki generate certificate running://test.crt x509 private-key running://test.key days 3650 subject "/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*."
Generated X.509 certificate at 'running://test.crt'
Configuration commands
Now, we can create a new service instance and bind it to a local port.
Example:
set service traffic-proxy TRAFFIC_PROXY mode https
set service traffic-proxy TRAFFIC_PROXY port 3128
set service traffic-proxy TRAFFIC_PROXY x509 ca-cert running://test.crt
set service traffic-proxy TRAFFIC_PROXY x509 ca-key running://test.key
Then, we need to create and attach a traffic policy to intercept the traffic:
set traffic selector TCP_TRAFFIC rule 1 protocol tcp
set traffic selector TCP_TRAFFIC rule 1 destination port 80,443
set traffic policy TPROXY rule 1 selector TCP_TRAFFIC
set traffic policy TPROXY rule 1 action proxy tcp 3128
set interfaces eth0 traffic policy in TPROXY
set interfaces eth1 traffic policy in TPROXY
We have created a new traffic selector to match all TCP traffic with destination
port equals to 80 or 443 (normally these ports are used for HTTP and HTTPs
respectively). Then, we have assigned that traffic selector to a new traffic
policy that proxies the traffic to our local port. Finally, we have attached
the traffic policy to the incoming hook of two physical interfaces: eth0 and
eth1.
Monitoring commands
We can run the command service traffic-proxy TRAFFIC_PROXY show connections
to display the latest connections that were intercepted.
Example:
admin@DUT0$ service traffic-proxy TRAFFIC_PROXY show connections
2023-09-21 21:08:09 UTC CONN: ssl 10.0.0.2 1234 192.168.1.2 443 sni:- names:Server sproto:TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384 dproto:TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384 origcrt:188178F6F7097DC76C12FB0330D1629EBE357D78 usedcrt:D79EB0BA11576DB6233725C8E3A7807642F0F31F user:-
We can see that a SSL connection that was started in 10.0.0.2:1234 and destined to the server 192.168.1.2:443 was intercepted at 2023-09-21 21:08:09. There’s more information like the TLS version that was used in both connections, the encryption algorithms, etc.
We can also configure the option
set service traffic-proxy TRAFFIC_PROXY logging content and then run the
command service traffic-proxy TRAFFIC_PROXY show content to display
information about the decrypted session.
Example:
admin@DUT0$ service traffic-proxy TRAFFIC_PROXY show content
2023-09-21 21:08:10 UTC [10.0.0.2]:1234 -> [192.168.1.2]:443 (18):
Hello from client
2023-09-21 21:08:10 UTC [192.168.1.2]:443 -> [10.0.0.2]:1234 (18):
Hello from server
2023-09-21 21:08:10 UTC [10.0.0.2]:1234 -> [192.168.1.2]:443 (EOF)
Block
The traffic-proxy service can serve block pages for connections that have been marked with a connmark by an external service or utility. The traffic-proxy intercepts these marked connections and serves a customizable HTML page to the user, informing them that the connection has been blocked.
This provides a more informative experience for end users compared to a silent drop, since they receive a clear notification explaining why their connection was denied.
Block template
The block page is rendered from an HTML template file. The template supports
placeholders using the {{ variable }} syntax, which are replaced with the
configured variable values when the page is served.
If no custom template file is configured, a default template is used.
To configure a custom template file and its variables:
set service traffic-proxy <NAME> block template file <path>
set service traffic-proxy <NAME> block template variable <var> value <val>
Where <path> is the path to the HTML template file and <var>/<val>
are the variable name and value pairs used to populate the template
placeholders.
Note
Variable names must start with a letter and can only contain letters,
numbers and underscores (e.g., REASON, carrier_name). Variable
values can contain spaces.
Block rules
Block rules define which marked connections should be intercepted by the traffic-proxy. Each rule matches connections based on their connmark value.
set service traffic-proxy <NAME> block rule <ID> connmark mark <mark>
set service traffic-proxy <NAME> block rule <ID> connmark vrf-mark <vrf>
set service traffic-proxy <NAME> block rule <ID> connmark extra-mark 1 value <mark>
Where <ID> is a numeric identifier for the rule and <mark> is the
connmark value set on the blocked connections.
Note
Only one connmark type can be configured per rule: either mark,
vrf-mark or extra-mark 1.
Each rule can also define its own variable overrides, which take precedence over the template-level variables:
set service traffic-proxy <NAME> block rule <ID> set variable <var> value <val>
This allows different block rules to customize the block page content. For example, different rules could display different messages depending on the type of threat detected by an external service or utility.
Monitoring commands
In order to use the block monitoring commands (show connections blocked
and monitor connections blocked), the logging connection option must
be enabled on the traffic-proxy instance:
set service traffic-proxy <NAME> logging connection
The following operational commands are available to monitor block activity:
service traffic-proxy <NAME> show stats: displays general statistics, including a blocked row with total counts of blocked connections.service traffic-proxy <NAME> show stats detailed: displays a detailed breakdown of statistics per block rule. A JSON variant is also available withservice traffic-proxy <NAME> show stats detailed json.service traffic-proxy <NAME> show connections blocked: displays the historical log of blocked connections. Requireslogging connectionto be enabled.service traffic-proxy <NAME> monitor connections blocked: displays blocked connections in real time. Requireslogging connectionto be enabled.
Example of show stats:
admin@osdx$ service traffic-proxy TRAFFIC_PROXY show stats
Statistics for instance "TRAFFIC_PROXY":
-----------------------------
name packets bytes
-----------------------------
intercepted 117 17304
queue - orig 0 0
queue - reply 0 0
error 0 0
blocked 113 17080
Example of show stats detailed:
admin@osdx$ service traffic-proxy TRAFFIC_PROXY show stats detailed
Statistics for instance "TRAFFIC_PROXY":
-----------------------------
name packets bytes
-----------------------------
intercepted 117 17304
queue - orig 0 0
queue - reply 0 0
error 0 0
blocked 113 17080
Blocking statistics for instance "TRAFFIC_PROXY":
---------------------
rule packets bytes
---------------------
1 113 17080
---------------------
Total 113 17080
When a connection is blocked, the traffic-proxy serves the rendered block page
with an HTTP 200 response for navigation requests. For embedded resources
an HTTP 403 response is returned instead.
Customizing the block page
The block page served to the user can be fully customized using an HTML template file with placeholders. The following example shows how to create a template and configure the traffic-proxy to use it.
First, create an HTML template file (e.g., running://block.html) with
placeholders:
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<p>Reference: {{ reference_code }}</p>
</body>
</html>
Then, configure the traffic-proxy instance with the block template, default variables and a rule matching the connmark:
set service traffic-proxy TPROXY block template file running://block.html
set service traffic-proxy TPROXY block template variable title value "Access Denied"
set service traffic-proxy TPROXY block template variable message value "This connection has been blocked."
set service traffic-proxy TPROXY block template variable reference_code value "REF-000"
set service traffic-proxy TPROXY block rule 1 connmark mark 100
set service traffic-proxy TPROXY block rule 1 set variable message value "Blocked by security policy."
set service traffic-proxy TPROXY block rule 1 set variable reference_code value "POL-100"
set service traffic-proxy TPROXY logging connection
In this example, when rule 1 matches (connmark 100), the message and
reference_code variables are overridden with rule-specific values, while
title keeps its default value.
More examples of block page customization are available in the Traffic-Proxy Basic examples page.
Blocking with firewall
This example shows how to use the Firewall
to detect and block specific HTTP/s traffic (e.g., connections to
webserver.com) and have the traffic-proxy serve a block page.
The firewall uses the block keyword in a rule together with the capture
block feature to accept the packet and mark the connection with a connmark.
The traffic-proxy then intercepts connections with that mark and serves the
block page.
First, create a firewall rules file (e.g., running://block.rules):
drop tls any any -> any any (msg:"Blocked traffic to webserver.com"; block; tls.sni; content:"webserver.com"; sid:1; rev:1;)
Note
The example above uses a TLS rule (tls.sni), but rules for
plain HTTP traffic can also be used. For example:
drop http any any -> any 80 (msg:"Block HTTP"; block; http.host; content:"webserver.com"; sid:2; rev:1;)
Then, configure the traffic infrastructure. A traffic queue is created for
the firewall, and a traffic selector ensures that already-marked connections
(connmark 1000) are not enqueued again (bypass):
set traffic queue Q elements 0
set traffic selector HTTPS_FIREWALL rule 1 destination port-group PORTS
set traffic selector HTTPS_FIREWALL rule 1 not connmark 1000
set traffic selector HTTPS_FIREWALL rule 1 protocol tcp
set traffic selector HTTPS_FIREWALL rule 2 not connmark 1000
set traffic selector HTTPS_FIREWALL rule 2 protocol tcp
set traffic selector HTTPS_FIREWALL rule 2 source port-group PORTS
set traffic policy HTTPS_FIREWALL rule 1 action enqueue Q
set traffic policy HTTPS_FIREWALL rule 1 selector HTTPS_FIREWALL
Configure the firewall instance with the capture block action:
set service firewall FWL mode inline queue Q
set service firewall FWL ruleset file running://block.rules
set service firewall FWL logging outputs fast
set service firewall FWL tls-detection detection-ports 443
set service firewall FWL bypass action block set connmark mark 1000
Finally, configure the traffic-proxy block rule to match the connmark set by the firewall:
set service traffic-proxy TRAFFIC_PROXY block rule 1 connmark mark 1000
Tip
The firewall also supports extra-mark 1 and vrf-mark for the
capture block action.
Further information about the firewall service and the capture block feature can be found at the Firewall chapter. More examples of blocking with firewall are available in the Traffic-Proxy Firewall examples page.
Blocking with app-id
This example shows how to use the application identification system
(app-detect) to detect and block traffic based on the identified
application, without using a firewall instance.
A custom app-id dictionary is configured to identify connections to
webserver.com. A traffic policy then sets a connmark on the detected
connections, and the traffic-proxy serves a block page for them.
Configure the app-detect dictionary to identify the target application:
set system conntrack app-detect dictionary 1 custom app-id 1 fqdn webserver.com
set system conntrack app-detect ssl-host
set system conntrack app-detect http-host
Create a traffic selector that matches detected applications and a traffic policy that sets the connmark:
set traffic selector BLOCKED_APP rule 1 app-detect app-id custom -1
set traffic selector BLOCKED_APP rule 1 app-detect state detected
set traffic policy BLOCKED_APP rule 1 selector BLOCKED_APP
set traffic policy BLOCKED_APP rule 1 set connmark 1000
Attach the traffic policy to the interface:
set interfaces ethernet eth1 traffic policy in BLOCKED_APP priority very-high
Finally, configure the traffic-proxy block rule to match the connmark:
set service traffic-proxy TRAFFIC_PROXY block rule 1 connmark mark 1000
Tip
App-id dictionaries can also be configured using XML dictionary
files with set system conntrack app-detect dictionary <priority> filename <path>.
Further information about the application identification system can be found at the Conntrack chapter. More examples of blocking with app-id are available in the Traffic-Proxy App Id examples page.