# Blocking single TLS SNI

**URL:** https://discourse.haproxy.org/t/blocking-single-tls-sni/4187
**Category:** Help!
**Created:** [August 12, 2019, 1:29pm UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187 "2019-08-12T13:29:53Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![kevin-dafm](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kevin-dafm](https://discourse.haproxy.org/u/kevin-dafm)
#### Post date: [August 12, 2019, 1:29pm UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/1 "2019-08-12T13:29:53Z")

</div>

Hello HAProxy community,

I have HAProxy acting as Load Balancer to a Kubernetes Cluster. I have a wildcard DNS entry for my “public” IP address on the HAProxy. I also have a wild card TLS Certificate.

When I deploy a new application on Kubernetes it appears as new\_application.mykyubdomain.com. Internally I access this no problem. This is combination of wild card DNS, TLS SNI and HAProxy magic working.

I would like to block a single application (TLS SNI) on the HAProxy. So my understanding is I need to inspect the SNI to see which application (TLS SNI) I am looking at and block it using tcp-request content reject.

This a snippet from the frontend section of my HAProxy settings for Kubernetes Cluster.

tcp-request inspect-delay 5s  
tcp-request content accept if { req\_ssl\_hello\_type 1 }  
acl stop\_app\_ssl req\_ssl\_sni new\_application1.mykyubdomain.com  
tcp-request content reject if stop\_app\_ssl

This is all in mode tcp as it is TLS traffic. The TLS termination is on the Kubernetes Cluster. I am not off loading the encryption to the HAProxy.

I have set-up Wireshark and can the SNI “new\_application1.mykyubdomain.com” in TLS extension SNI when I connect to new\_application1 but HAProxy does not block the traffic.

I have the following version of HAProxy running on rhel 7.

What am I doing wrong? Any advice much appreciated. If I have not made anything clear please ask.

[root@rhoslb1 haproxy]# haproxy -vv  
HA-Proxy version 1.5.18 2016/05/10  
Copyright 2000-2016 Willy Tarreau [willy@haproxy.org](mailto:willy@haproxy.org)

Build options :  
TARGET = linux2628  
CPU = generic  
CC = gcc  
CFLAGS = -O2 -g -fno-strict-aliasing -DTCP\_USER\_TIMEOUT=18  
OPTIONS = USE\_LINUX\_TPROXY=1 USE\_GETADDRINFO=1 USE\_ZLIB=1 USE\_REGPARM=1 USE\_OPENSSL=1 USE\_PCRE=1

Default settings :  
maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200

Encrypted password support via crypt(3): yes  
Built with zlib version : 1.2.7  
Compression algorithms supported : identity, deflate, gzip  
Built with OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017  
Running on OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017  
OpenSSL library supports TLS extensions : yes  
OpenSSL library supports SNI : yes  
OpenSSL library supports prefer-server-ciphers : yes  
Built with PCRE version : 8.32 2012-11-30  
PCRE library supports JIT : no (USE\_PCRE\_JIT not set)  
Built with transparent proxy support using: IP\_TRANSPARENT IPV6\_TRANSPARENT IP\_FREEBIND

Best Regards,

Kevin.

---

<div class="post-metadata">

### Author: ![lukastribus](https://avatars.discourse-cdn.com/v4/letter/l/7ea924/32.png) [@lukastribus](https://discourse.haproxy.org/u/lukastribus)
#### Post date: [August 12, 2019, 6:39pm UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/2 "2019-08-12T18:39:15Z")

</div>

Share the entire configuration please.

---

<div class="post-metadata">

### Author: ![kevin-dafm](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kevin-dafm](https://discourse.haproxy.org/u/kevin-dafm)
#### Post date: [August 13, 2019, 7:49am UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/3 "2019-08-13T07:49:12Z")

</div>

# Global settings

#---------------------------------------------------------------------  
global  
maxconn 20000  
log /dev/log local0 info  
chroot /var/lib/haproxy  
pidfile /var/run/haproxy.pid  
user haproxy  
group haproxy  
daemon

```
# turn on stats unix socket
stats socket /var/lib/haproxy/stats

```

#---------------------------------------------------------------------  
#Global settings  
#---------------------------------------------------------------------  
global  
maxconn 20000  
log /dev/log local0 info  
chroot /var/lib/haproxy  
pidfile /var/run/haproxy.pid  
user haproxy  
group haproxy  
daemon

```
# turn on stats unix socket
stats socket /var/lib/haproxy/stats

```

#---------------------------------------------------------------------  
#common defaults that all the ‘listen’ and ‘backend’ sections will  
#use if not designated in their block  
#---------------------------------------------------------------------  
defaults  
mode http  
log global  
option tcplog  
option dontlognull  
option redispatch  
retries 3  
timeout http-request 10s  
timeout queue 1m  
timeout connect 10s  
timeout client 300s  
timeout server 300s  
timeout http-keep-alive 10s  
timeout check 10s  
maxconn 20000

listen stats  
bind :9000  
mode http  
stats enable  
stats uri /

frontend atomic-openshift-api  
bind 10.2.134.171:443  
default\_backend atomic-openshift-api  
mode tcp  
option tcplog

backend atomic-openshift-api  
balance source  
mode tcp  
server [master1.mydomain.com](http://master1.mydomain.com) [rhosmaster1.mydomain.com:443](http://rhosmaster1.mydomain.com:443) check  
server [master2.mydomain.com](http://master2.mydomain.com) [rhosmaster2.mydomain.com:443](http://rhosmaster2.mydomain.com:443) check  
server [master3.mydomain.com](http://master3.mydomain.com) [rhosmaster3.mydomain.com:443](http://rhosmaster3.mydomain.com:443) check

frontend infrarouter  
bind 10.2.134.172:80  
default\_backend infrarouter  
mode http  
option tcplog  
option forwardfor except 127.0.0.0/8

```
# below is ACL to block by hostname

```

#acl restricted\_page hdr(host) -i [bird-test-kevintest.apps.mydomain.com](http://bird-test-kevintest.apps.mydomain.com)  
# ACL for specific IP addresses  
#acl restrited\_source\_ip src 10.2.8.152  
#acl restrited\_source\_ip\_gs src 10.2.8.162  
#http denty request based on the ACLs  
#http-request deny if restricted\_page restrited\_source\_ip\_gs

backend infrarouter  
balance source  
mode http  
server [infra1.mydomain.com](http://infra1.mydomain.com) [rhosinfra1.mydomain.com:80](http://rhosinfra1.mydomain.com:80) check  
server [infra2.mydomain.com](http://infra2.mydomain.com) [rhosinfra2.mydomain.com:80](http://rhosinfra2.mydomain.com:80) check  
server [infra3.mydomain.com](http://infra3.mydomain.com) [rhosinfra3.mydomain.com:80](http://rhosinfra3.mydomain.com:80) check

frontend infrarouter-secure  
bind 10.2.134.172:443  
default\_backend infrarouter-secure  
mode tcp  
option tcplog

```
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl stop_app_ssl req_ssl_sni django-ex-kevintest.apps.mydomain.com
tcp-request content reject if stop_app_ssl

```

backend infrarouter-secure  
balance source  
mode tcp  
server [infra1.mydomain.com](http://infra1.mydomain.com) [rhosinfra1.mydomain.com:443](http://rhosinfra1.mydomain.com:443) check  
server [infra2.mydomain.com](http://infra2.mydomain.com) [rhosinfra2.mydomain.com:443](http://rhosinfra2.mydomain.com:443) check  
server [infra3.mydomain.com](http://infra3.mydomain.com) [rhosinfra3.mydomain.com:443](http://rhosinfra3.mydomain.com:443) check

"# use if not designated in their block  
#---------------------------------------------------------------------  
defaults  
mode http  
log global  
option tcplog  
option dontlognull  
option redispatch  
retries 3  
timeout http-request 10s  
timeout queue 1m  
timeout connect 10s  
timeout client 300s  
timeout server 300s  
timeout http-keep-alive 10s  
timeout check 10s  
maxconn 20000

listen stats  
bind :9000  
mode http  
stats enable  
stats uri /

frontend atomic-openshift-api  
bind 10.2.134.171:443  
default\_backend atomic-openshift-api  
mode tcp  
option tcplog

backend atomic-openshift-api  
balance source  
mode tcp  
server [master1.mydomain.com](http://master1.mydomain.com) [rhosmaster1.mydomain.com:443](http://rhosmaster1.mydomain.com:443) check  
server [master2.mydomain.com](http://master2.mydomain.com) [rhosmaster2.mydomain.com:443](http://rhosmaster2.mydomain.com:443) check  
server [master3.mydomain.com](http://master3.mydomain.com) [rhosmaster3.mydomain.com:443](http://rhosmaster3.mydomain.com:443) check

frontend infrarouter  
bind 10.2.134.172:80  
default\_backend infrarouter  
mode http  
option tcplog  
option forwardfor except 127.0.0.0/8

```
#below is ACL to block by hostname

```

#acl restricted\_page hdr(host) -i [bird-test-kevintest.apps.mydomain.com](http://bird-test-kevintest.apps.mydomain.com)  
#ACL for specific IP addresses  
#acl restrited\_source\_ip src 10.2.8.152

# acl restrited\_source\_ip\_gs src 10.2.8.162

```
# http denty request based on the ACLs

```

# http-request deny if restricted\_page restrited\_source\_ip\_gs

backend infrarouter  
balance source  
mode http  
server [infra1.mydomain.com](http://infra1.mydomain.com) [rhosinfra1.mydomain.com:80](http://rhosinfra1.mydomain.com:80) check  
server [infra2.mydomain.com](http://infra2.mydomain.com) [rhosinfra2.mydomain.com:80](http://rhosinfra2.mydomain.com:80) check  
server [infra3.mydomain.com](http://infra3.mydomain.com) [rhosinfra3.mydomain.com:80](http://rhosinfra3.mydomain.com:80) check

frontend infrarouter-secure  
bind 10.2.134.172:443  
default\_backend infrarouter-secure  
mode tcp  
option tcplog

```
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl stop_app_ssl req_ssl_sni django-ex-kevintest.apps.mydomain.com
tcp-request content reject if stop_app_ssl

```

backend infrarouter-secure  
balance source  
mode tcp  
server [infra1.mydomain.com](http://infra1.mydomain.com) [rhosinfra1.mydomain.com:443](http://rhosinfra1.mydomain.com:443) check  
server [infra2.mydomain.com](http://infra2.mydomain.com) [rhosinfra2.mydomain.com:443](http://rhosinfra2.mydomain.com:443) check  
server [infra3.mydomain.com](http://infra3.mydomain.com) [rhosinfra3.mydomain.com:443](http://rhosinfra3.mydomain.com:443) check

---

<div class="post-metadata">

### Author: ![lukastribus](https://avatars.discourse-cdn.com/v4/letter/l/7ea924/32.png) [@lukastribus](https://discourse.haproxy.org/u/lukastribus)
#### Post date: [August 13, 2019, 8:01am UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/4 "2019-08-13T08:01:34Z")

</div>

We must not accept the the content earlier.

Try something like this:

```
acl stop_app_ssl req_ssl_sni django-ex-kevintest.apps.mydomain.com
tcp-request inspect-delay 5s
tcp-request content reject if { req_ssl_hello_type 1 stop_app_ssl }
tcp-request content accept if { req_ssl_hello_type 1 ! stop_app_ssl }
tcp-request content reject
```

---

<div class="post-metadata">

### Author: ![kevin-dafm](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kevin-dafm](https://discourse.haproxy.org/u/kevin-dafm)
#### Post date: [August 13, 2019, 8:28am UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/5 "2019-08-13T08:28:20Z")

</div>

Thanks for quick response!

That does not work unfortunately. It complains when I put the configuration in place. I think this is just a syntax issue?

Below is error.

root@rhoslb1 haproxy]# haproxy -f /etc/haproxy/haproxy.cfg -d  
[ALERT] 224/092416 (67628) : parsing [/etc/haproxy/haproxy.cfg:117] : ‘tcp-request content reject’ : error detected in frontend ‘infrarouter-secure’ while parsing ‘if’ condition : ‘stop\_app\_ssl’ is not a number  
[ALERT] 224/092416 (67628) : parsing [/etc/haproxy/haproxy.cfg:118] : ‘tcp-request content accept’ : error detected in frontend ‘infrarouter-secure’ while parsing ‘if’ condition : ‘!’ is not a number  
[ALERT] 224/092416 (67628) : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg  
[ALERT] 224/092416 (67628) : Fatal errors found in configuration.  
[root@rhoslb1 haproxy]#

Like I say I think syntax problem with the and for the tcp-request content accept / reject rules.

I have tried the following

acl stop\_app\_ssl req\_ssl\_sni [django-ex-kevintest.mydomain.com](http://django-ex-kevintest.mydomain.com)  
tcp-request inspect-delay 5s  
tcp-request content reject if { req\_ssl\_hello\_type 1 } stop\_app\_ssl  
tcp-request content accept if { req\_ssl\_hello\_type 1 } ! stop\_app\_ssl  
tcp-request content reject

The configuration starts with no errors but the application (site django-ex-kevintest) is still accessible. I want to block it.

I am checking out what the correct syntax and in tcp-request content is?

Kevin.

---

<div class="post-metadata">

### Author: ![kevin-dafm](https://avatars.discourse-cdn.com/v4/letter/k/90ced4/32.png) [@kevin-dafm](https://discourse.haproxy.org/u/kevin-dafm)
#### Post date: [August 13, 2019, 8:50am UTC](https://discourse.haproxy.org/t/blocking-single-tls-sni/4187/6 "2019-08-13T08:50:04Z")

</div>

I restarted the haproxy with the new entry below and it works.

acl stop\_app\_ssl req\_ssl\_sni django-ex-kevintest.apps.rhos.agriculture.gov.ie  
tcp-request inspect-delay 5s  
tcp-request content reject if { req\_ssl\_hello\_type 1 } stop\_app\_ssl  
tcp-request content accept if { req\_ssl\_hello\_type 1 } !stop\_app\_ssl  
tcp-request content reject

Thanks so much for solution Lukastribus.

You Rock!!!
