Pluggable transports like meek and obfs4 can be difficult to use outside of Tor. That’s because they communicate with a parent process using a specification that is not widely implemented. ptadapter wraps pluggable transports to provide a simple local TCP interface so that pluggable transports can easily be used by other programs.

Author’s announcement:

Here is a tutorial on using ptadapter and obfs4 to obfuscate a simple HTTP proxy.


Install the dependencies.

$ sudo apt install python3-pip obfs4proxy ncat
$ sudo pip3 install ptadapter

Run your HTTP proxy, listening on a localhost port. (You can replace this step with any kind of server you want.)

$ ncat -l -k --proxy-type http 3128

Create a file called ptadapter.ini. The format is documented here

exec = /usr/bin/obfs4proxy
state = pt_state
forward =
tunnels = server_obfs4
transport = obfs4
listen = # replace this with a port of your choice

Run ptadapter on the configuration file. Now you have an external obfs4 listener on that will deobfuscate traffic and forward it to

$ ptadapter -S ptadapter.ini

Get the bridge’s certificate for pt_state/obfs4_bridgeline.txt. The important part is cert=..., the obfs4 server’s public key information. You will need it when setting up the client.

$ cat pt_state/obfs4_bridgeline.txt
Bridge obfs4 <IP ADDRESS>:<PORT> <FINGERPRINT> cert=1/x+AlgQH0T9ZD23FUzs7SeYzDFhxIXjlbTwU7ExkAXVAmi601C4S4Auk+oRqniAIbqmXg iat-mode=0


Install the dependencies.

$ sudo apt install python3-pip obfs4proxy
$ sudo pip3 install ptadapter

Create a file called ptadapter.ini. Copy the values for options-cert and options-iat-mode from pt_state/obfs4_bridgeline.txt on the server.

exec = /usr/bin/obfs4proxy
state = pt_state
tunnels = client_obfs4
transport = obfs4
listen =
upstream = <IP address of server>:9999
options-cert = 1/x+AlgQH0T9ZD23FUzs7SeYzDFhxIXjlbTwU7ExkAXVAmi601C4S4Auk+oRqniAIbqmXg
options-iat-mode = 0

Run ptadapter on the configuration file. Now you have a local listener at that will obfuscate and forward to server:9999, which will then deobfuscate and forward to its own Basically, the client’s port 3128 is connected to the server’s port 3128 through a magic obfuscated tunnel.

$ ptadapter -C ptadapter.ini

Now you can test the tunnel, treating the client’s local as if it were an HTTP proxy.

$ curl -x
<IP address of server>

You can also configure in your web browser, etc.


Use the -v option to make ptadapter more verbose.

$ ptadapter -vv -S ptadapter.ini
$ ptadapter -vv -C ptadapter.ini

Enable obfs4proxy logging in ptadapter.ini. The logs will appear in pt_state/obfs4proxy.log.

exec = /usr/bin/obfs4proxy --enableLogging --unsafeLogging --logLevel=DEBUG