Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
169 lines (119 sloc) 5.57 KB


netfilter/xtables module: match SSL/TLS certificate fingerprints


iptables -I <chain> .. -m sslpin [!] --fpl <fingerprint list id> ..


For an introduction to SSL/TLS certificate pinning refer to the OWASP pinning cheat sheet. xt_sslpin lets you do certificate pinning at the netfilter level. xt_sslpin will match certificate fingerprints in SSL/TLS connections (with minimal performance impact). Applications are expected to do further certificate chain validation and signature checks (i.e. normal SSL/TLS processing).


  1. Mark connections matching on list 0

    iptables -I INPUT -p tcp --sport 443 \
        -m conntrack --ctstate ESTABLISHED \
        -m sslpin --fpl 0 \
        -j CONNMARK --set-mark 1
  2. Add certificate to list 0

    echo \
    | openssl s_client -connect -servername 2>/dev/null \
    | openssl x509 -outform DER \
    | sha1sum > /sys/kernel/xt_sslpin/0_add
  3. Drop marked connections

    iptables -I INPUT -j CONNMARK --restore-mark
    iptables -A INPUT -m connmark --mark 1 -j DROP
    iptables -A INPUT -j CONNMARK --save-mark
  4. Test (should time out)

    curl --connect-timeout 5
  5. Reset (will remove all rules from INPUT chain)

    iptables -F INPUT



  • linux kernel > 3.7
  • kernel-headers
  • iptables-dev
  • gcc
  • git


git clone
cd xt_sslpin
sudo apt-get install iptables-dev # xtables.h

Build and install:

sudo make install

Verify installation:

iptables -m sslpin -h


make clean
sudo make uninstall


Options preceded by an exclamation mark negate the comparison: the rule will match if the presented SSL/TLS certificate fingerprint is NOT found in the specified list.

[!] --fpl <list id>

If a "Certificate" message is seen, match if one of the certificates matches a fingerprint in the given list.


The list API is exposed under: /sys/kernel/xt_sslpin/.

Operation Command
ADD echo fingerprint-sha1 > /sys/kernel/xt_sslpin/<list id>_add
REMOVE echo fingerprint-sha1 > /sys/kernel/xt_sslpin/<list id>_rm
LIST ls /sys/kernel/xt_sslpin/<list id>


Per connection, the incoming handshake data is parsed once across all -m sslpin iptables rules; upon receiving the SSL/TLS handshake ServerCertificate message, the parsed certificates are checked by all rules.

xt_sslpin intercepted SSL/TLS handshake

After this, the connection is marked as "finished", and xt_sslpin will not do any further checking. (Re-handshaking will not be checked in order to incur minimal overhead, and as the server has already proved its identity).

Up until the ServerCertificate message is received, xt_sslpin will drop out-of-order TCP segments to parse the data linearly without buffering. Conntrack takes care of IP fragment reassembly up-front, but packets can still have non-linear memory layout; see skb_is_nonlinear().

If SYN is received on a time-wait state conn/flow, conntrack will destroy the old cf_conn and create a new cf_conn. Thus, our per-conn state transitions are simply new->open->destroyed (no reopen).


Compile and install the module in debug mode

sudo make debug install

and it will log connection information, fingerprints and parsing information:

kernel: [353.333720] xt_sslpin 2.0 (SSL/TLS pinning)
kernel: [353.333722] xt_sslpin: debug enabled
kernel: [353.191650] xt_sslpin: new fingerprint (list = 0, fp = AD7CEA1CD3C13E1DE21C6ED5C16E4D156CE651E6, bucket = 44412)
kernel: [353.191753] xt_sslpin: new fingerprint (list = 0, fp = 65548323AA33D1FE5A1FE1AF5EA35E4846AEF466, bucket = 28865)
kernel: [353.191830] xt_sslpin: new fingerprint (list = 0, fp = 9DBFAD0F0EEDC153E1D51E56165ED165E16E165E, bucket = 40383)
kernel: [353.332684] xt_sslpin: 1 connection (0 actively monitored)
kernel: [353.332707] xt_sslpin: SYN/ACK not seen for connection (already established when xt_sslpin was loaded) - ignoring connection
kernel: [353.575060] xt_sslpin: 2 connections (0 actively monitored)
kernel: [353.575082] xt_sslpin: SYN/ACK not seen for connection (already established when xt_sslpin was loaded) - ignoring connection


  • Optional buffering for reordered TCP segments during handshake (no RTT penalty / overhead)
  • TCP Fast Open (TFO) support
  • Restrict TCP Options / TCP stack passthrough
  • IPv6 support


This module is a fork from xt_sslpin by fredburger (

Thank you!


xt_sslpin is Copyright (C) 2016 Enteee (

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.