Juniper SRX Branch - Blocking HTTPS websites using the AppFW (application-firewall) feature - Part 1
Juniper SRX Branch - Blocking HTTPS websites using the AppFW (application-firewall) featureTools and utilities used:
- Juniper SRX210-HE
- Junos 12.1X44-D15
- FreeBSD 7.4
- OpenSSL 1.0.1 ( version is necessary for SNI extension)
- Nginx
- tcpdump
- setfib
In order to generate client-to-server and server-to-client traffic from one FreeBSD 7 box without jail and any kind of virtual machines (it's a Pentium 3 box), I had to use different routing tables (or forwarding tables) for client and server. For this, support for multiple FIBs needs to be compiled in the FreeBSD kernel.
Network diagram below:
Attachment:
File comment: Juniper SRX Application firewall blocking HTTPS websites based on Server Name Indication
appfw.png [19.37 KiB]
Downloaded 18133 times
Note1: Juniper High-End SRX devices support SSL Forward proxy (man in the middle) and can do Layer 7 inspection on the SSL traffic before encryption back to server/client, but branch devices can only do Layer 7 inspection on clear text protocols (unless a 3rd party proxy is used to terminat the SSL, but that's not the point of this article).
Note2: However, protocol TLS v1.0 and above has an extension called SNI (Server Name Indication and all modern browsers support it), where the TLS/HTTPS client that chooses TLS protocol sends in the client hello packet also the name of the destination domain. This SNI extension allows multiple HTTPS domains to be hosted on one public IP address. Without this, only one HTTPS virtual host could be bound to an IP address and this is because the domain information was contained in the encrypted HTTP GET/POST request and the webserver had to first decrypt to get the domain. In order to decrypt the HTTPS connection, it needed to know the SSL parameters (certificate, ciphers, etc) and it couldn't do that without knowing the virtual host ( beacuse all web servers have different configurations for different domains - virtual hosts)... With SNI, the client tells the web server in clear text what domain it intends to connect to via HTTPS and the webserver can load SSL settings for that domain before decrypting it (Cool, ha ?).
Here's a wireshark snapshot of the Server Name Indication extension to TLS1.0 protocol:
Attachment:
File comment: TLS Server Name Indication Wireshark preview
tls_sni.png [19.9 KiB]
Downloaded 18133 times
The "Client Hello" packet is the first packet sent from the client (Browser) to the HTTPS Server after TCP 3 way handshake is done (in normal situations) and it initializes the SSL/TLS handshake.
Step 1: Preparing the FreeBSD interfaces and Forwarding Information Bases as well as the HTTPS server (nginx).
Code:
# sysctl net.fibs
net.fibs: 4
Good. I have 4 FIBs to play with, but I'll need only two.
Code:
# ifconfig vlan120
vlan120: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 00:07:e9:a5:9b:fa
inet 10.1.120.2 netmask 0xffffff00 broadcast 10.1.120.255
media: Ethernet autoselect (1000baseTX <full-duplex>)
status: active
vlan: 120 parent interface: em0
# ifconfig vlan121
vlan121: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 00:07:e9:a5:9b:fa
inet 10.1.121.2 netmask 0xffffff00 broadcast 10.1.121.255
media: Ethernet autoselect (1000baseTX <full-duplex>)
status: active
vlan: 121 parent interface: em0
I'll be using interfaces vlan120 (fib 1) and vlan121 (fib 2):
Code:
# setfib 1 route add 10.1.121.2/32 10.1.120.1
add net 10.1.121.2: gateway 10.1.120.1
# setfib 2 route add 10.1.120.2/32 10.1.121.1
add net 10.1.120.2: gateway 10.1.121.1
# setfib 1 route add 10.1.121.2/32 10.1.120.1
add net 10.1.121.2: gateway 10.1.120.1
# setfib 2 route add 10.1.120.2/32 10.1.121.1
add net 10.1.120.2: gateway 10.1.121.1
So FIB1 routing table will have a route to 10.1.121.2/32 (HTTPS client) to gateway 10.1.120.1 (SRX-1) and FIB2 routing table will have a route to 10.1.120.2/32(HTTP server) to gateway 10.1.121.1(SRX-2).
Nnginx configuration needs to be instructed to listen on the specific IP and fib (See
http://nginx.org/en/docs/http/ngx_http_core_module.html and search for "setfib"):
Code:
nginx.conf:
server {
listen 10.1.120.2:443 setfib=1;
...
Let's do a test tcptraceroute (why tcptraceroute ? for obvious reasons) from client towards server:
Code:
# setfib 2 tcptraceroute -i vlan121 10.1.120.2 443
Selected device vlan121, address 10.1.121.2, port 58165 for outgoing packets
Tracing the path to 10.1.120.2 on TCP port 443, 30 hops max
1 10.1.121.1 (10.1.121.1) 9.345 ms 9.496 ms 9.729 ms
2 10.1.114.1 (10.1.114.1) 9.682 ms 9.684 ms 9.921 ms
3 10.1.120.2 (10.1.120.2) [open] 9.539 ms 9.674 ms 9.688 ms
Step 2: SRX-1 configuration (this box will do the layer7 inspection with Application Firewall feature):
SRX-1 interfaces:
Code:
set interfaces ge-0/0/0 vlan-tagging
set interfaces ge-0/0/0 mtu 1624
set interfaces ge-0/0/0 unit 114 vlan-id 114
set interfaces ge-0/0/0 unit 114 family inet address 10.1.114.1/24
set interfaces ge-0/0/0 unit 114 family iso
set interfaces ge-0/0/0 unit 114 family mpls
set interfaces ge-0/0/0 unit 120 vlan-id 120
set interfaces ge-0/0/0 unit 120 family inet mtu 1500
set interfaces ge-0/0/0 unit 120 family inet address 10.1.120.1/24
Defining a custom nested application for the HTTPS domain that needs to be blocked:
Code:
set services application-identification nested-application block-backbook-uri type BACKBOOK
set services application-identification nested-application block-backbook-uri protocol SSL
set services application-identification nested-application block-backbook-uri signature s01 member m01 context ssl-server-name
set services application-identification nested-application block-backbook-uri signature s01 member m01 pattern .*.backbook.com
set services application-identification nested-application block-backbook-uri signature s01 member m01 direction client-to-server
set services application-identification nested-application block-backbook-uri signature s01 maximum-transactions 1
Security zones:
Code:
set security zones security-zone TRUST host-inbound-traffic system-services all
set security zones security-zone TRUST host-inbound-traffic protocols all
set security zones security-zone TRUST interfaces ge-0/0/0.114
set security zones security-zone TRUST interfaces ge-0/0/0.120
Application-firewall ruleset that matches the nested application for domain "backbook.com" (nothing against this domain, seems unregistered at the moment of this writing) as well as security policy that permits traffic with L7 inspection by AppFW:
Code:
set security application-firewall rule-sets filter-http rule 0 match dynamic-application block-backbook-uri
set security application-firewall rule-sets filter-http rule 0 then reject
set security application-firewall rule-sets filter-http default-rule permit
set security policies from-zone TRUST to-zone TRUST policy any match source-address any
set security policies from-zone TRUST to-zone TRUST policy any match destination-address any
set security policies from-zone TRUST to-zone TRUST policy any match application any
set security policies from-zone TRUST to-zone TRUST policy any then permit application-services application-firewall rule-set filter-http