Pages

Monday, 4 February 2013

Bypassing censorship by obfuscating your traffic using obfsproxy

Some countries like China, Iran, Ethiopia, Kazakhstan and others, like installing some nasty little boxes at the edges of their country’s “internet feed” to monitor and filter traffic. These little boxes are called DPI (Deep Packet Inspection) boxes and what they do, is sniff out every little packet flowing through them to find specific patterns and then they provide their administrator with the option to block traffic that matches these patterns. These boxes are very sophisticated and they don’t just filter traffic by src, dst or port, they filter traffic by the content (payload) the packets carry.
Unfortunately, it’s not just these countries that deploy DPI technologies, but some private companies also use such devices in order to monitor their employees.
The 10 thousand feet view
Tor is a nice way to avoid basic censorship technologies, but sometimes DPI technology is so good that it can fingerprint Tor traffic, which is already encrypted, and block it. In response to that, Tor people devised a technology called Pluggable Transports whose job is to obfuscate traffic in various ways so that it looks like something different than it actually is. For example it can make Tor traffic look like a skype call using SkypeMorph or one can use Obfsproxy to obfuscate traffic to look like…nothing, or at least nothing easily recognizable. What’s cool about obfsproxy though is that one can even use it separately from Tor, to obfuscate any connection he needs to.
A warning
Even though obfsproxy encrypts traffic and makes it look completely random, it’s not a fool proof solution for everything. It’s basic job is to defend against DPI that can recognize/fingerprint TLS connections. If someone has the resources he could potentially train his DPI box to “speak” the obfsproxy protocol and eventually decrypt the obfuscated traffic. What this means is that obfsproxy should not be used as a single means of protection and it should just be used as a wrapper _around_ already encrypted SSL traffic.
If you’re still in doubt about what can obfsproxy protect you from and from what it can’t, please read the Obfsproxy Threat Model document.
Two use cases
Obfuscate an SSH and an OpenVPN connection.
Obviously one needs a server outside the censorship perimeter that he or someone else will run the obfsproxy server part. Instructions on installing obfsproxy on Debian/Ubuntu are given in my previous blog post setting up tor + obfsproxy + brdgrd to fight censhorship. Installing netcat, the openbsd version; package name is netcat-openbsd on Debian/Ubuntu, is also needed for the SSH example.
What both examples do is obfuscate a TLS connection through an obfsproxy server so that it looks innocent. Assuming that the most innocent looking traffic is HTTP, try running the obfsproxy server part on port 80.

SSH connection
Scenario:
USER: running ssh client
HOST_A (obfsproxy): running obfsproxy on port 80 and redirecting to HOST_B port 22
HOST_B (dst): Running SSH server on port 22
What one needs to do is setup the following “tunneling”:
ssh client —> [NC SOCKS PROXY] —> obfsproxy client (USER)—> obfsproxy server (HOST_A) —> ssh server (HOST_B)
Steps:
1. on HOST_A setup obfsproxy server to listen for connection and redirect to HOST_B:
# screen obfsproxy --log-min-severity=info obfs2 --dest=HOST_B:22 server 0.0.0.0:80
2. on USER’s box, then configure obfsproxy client to setup a local socks proxy that will obfuscate all traffic passing through it:
$ screen obfsproxy --log-min-severity=info obfs2 socks 127.0.0.1:9999
Then instead of SSH-ing directly to HOST_B, the user has to ssh to HOST_A port 80 (where obfsproxy server is listening).
3. on USER’s box again, edit ~/.ssh/config and add something along the following lines:
Host HOST_A
    ProxyCommand /bin/nc.openbsd -x 127.0.0.1:9999 %h %p
This will force all SSH connections to HOST_A to pass through the local (obfsproxy) socks server listening on 127.0.0.1:9999
4. Finally run the ssh command:
$ ssh -p 80 username@HOST_A
That’s it. The connection will now pass get obfuscated locally, pass through obfsproxy server at HOST_A and then finally reach it’s destination at HOST_B.
OpenVPN connection
Scenario:
USER: running OpenVPN client
HOST_A (obfsproxy): running obfsproxy on port 80 and redirecting to HOST_B TCP port 443
HOST_B (dst): Running OpenVPN server on port 443
What one needs to do is setup the following “tunneling”:
openvpn client —> obfsproxy client (USER)—> obfsproxy server (HOST_A) —> OpenVPN server (HOST_B)
Steps:
1. on HOST_A setup obfsproxy server to listen for connection and redirect to HOST_B:
# screen obfsproxy --log-min-severity=info obfs2 --dest=HOST_B:443 server 0.0.0.0:80
2. on USER’s box, then configure obfsproxy client to setup a local socks proxy that will obfuscate all traffic passing through it:
$ screen obfsproxy --log-min-severity=info obfs2 socks 127.0.0.1:9999
Then instead of connecting the OpenVPN client directly to HOST_B, the user has edit OpenVPN config file to connect to HOST_A port 80 (where obfsproxy server is listening).
3. on USER’s box again, edit your openvpn config file, change the ‘port’ and ‘remote’ lines and add a ‘socks-proxy’ one:

port 80
remote HOST_A
socks-proxy 127.0.0.1 9999

This will instruct the OpenVPN client to connect to HOST_A passing through the local (obfsproxy) socks server listening on 127.0.0.1:9999 4. Finally run the openvpn client command:
$ openvpn client.config
That’s it.
Security Enhancement
You can “enhance” obfproxy’s security by adding a shared secret parameter to command line, so anyone who doesn’t have this secret key won’t be able to use the obfsproxy server, decryption of packets will fail:
# screen obfsproxy --log-min-severity=info obfs2 --shared-secret="foobarfoo" --dest=HOST_B:443 server 0.0.0.0:80
$ screen obfsproxy --log-min-severity=info obfs2 --shared-secret="foobarfoo" socks 127.0.0.1:9999
Documentation
Or at least…some documentation.
Your best chance to understand the internals of obfsproxy is to read the protocol specification
For more info about obfsproxy client part, read the documentation here: obfsproxy client external
For more info about obfsproxy server part, read the documentation here: obfsproxy server external
Screenshots
For those who like meaningless screenshots, here’s what wireshark (which is certainly NOT a DPI) can tell about a connection without and with obfsproxy:
Without obfsproxy

With obfsproxy

*Update*
one can find openvpn configuration files for use with obfsproxy here:
Linux Client
Windows Client

from http://www.void.gr/kargig/blog/2012/10/05/bypassing-censorship-devices-by-obfuscating-your-traffic-using-obfsproxy/
-------------------------------------------------------

Use obfsproxy to obfuscate the openvpn traffic

Obfsproxy is a Tor subproject. It can be used to obfuscate (any) traffic so that it becomes unrecognizable. Obfuscating OpenVPN traffic using obfsproxy.


Use obfsproxy

Obfsproxy is a Tor subproject. It can be used to obfuscate (any) traffic so that it becomes unrecognizable. Obfuscating OpenVPN traffic using obfsproxy was suggested here, with one additional mail available here:
"However, the obfsproxy project sounds very interesting.  And it should be
possible to use obfsproxy (as it can talk like a SOCKS proxy) with
OpenVPN, by using the socks-proxy argument."

A quick obfsproxy setup

This setup will start obfsproxy on your openvpn server, listening to the port 21194. On the client it will start a obfsproxy serving as a SOCKS proxy, listening on the client on port 10194. The part which says "<some-random-key>" needs to be the same value on both server and client. The key can be a longer text string, with just random letters. I'd recommend to keep it long (at least 32 characters, which is 256 bits).

Client side

Add the following lines to your existing openvpn config file:
socks-proxy-retry
socks-proxy 127.0.0.1 10194
and change the --remote option to be
remote <YOUR-VPN-SERVER> 21194
That is, changing the port number to match the port number the server side obfsproxy will listen to.
Then start the obfsproxy like this:
 [user@host: ~] $ obfsproxy --log-file=obfsproxy.log --log-min-severity=info obfs2
 --shared-secret=<some-random-key> socks 127.0.0.1:10194

Server side

Here we tell obfsproxy to listen to TCP port 21194 and to send any obfsproxy clients to the OpenVPN server, listening on 127.0.0.1, port 1194. And remember to allow TCP connections from the "outside" to port 21194 in your firewall config. Start obfsproxy like this:
 [user@host: ~] $ obfsproxy --log-file=obfsproxy.log --log-min-severity=info obfs2
 --dest=127.0.0.1:1194 --shared-secret=<some-random-key> server 0.0.0.0:21194
The OpenVPN server needs in this case just this line in the config:
port 1194
That's all the magic, and should be a complete working setup. 
(不错。我测试成功。上述的1194可改为其他的端口号,比如11384。首先在/etc/openvpn/openvpn.conf中修改,即修改openvpn服务器端的端口号。) 

(【伺服器运行obfs】
# obfsproxy --log-min-severity=info obfs2 --shared-secret=
<some-random-key> --dest=127.0.0.1:11384 server 0.0.0.0:21195
       
【客戶端运行obfs】obfsproxy.exe --log-min-severity=info obfs2 --shared-secret=

<some-random-key> socks 127.0.0.1:10194    )

from https://community.openvpn.net/openvpn/wiki/TrafficObfuscation
( obfs4proxy-openvpn: Obfuscating OpenVPN traffic using obfs4proxy
 
This post provides a more in-depth look at the obfs4proxy-openvpn script. You don’t need to fully read it to make use of the script, but it will help you to get the most out of it.

Overview

After my initial post about obfs4 on how to hide any TCP traffic and an example for hiding SSH traffic, it’s now time to do so for OpenVPN.

For this, I have written a Bash script to do the job. It’s called obfs4proxy-openvpn and is freely available under MIT license.

Supported transports

obfs4

The main goal of the script is to provide obfs4 transport to OpenVPN. This is also the main interest of this article.

This transport requires out-of-band CERT exchange between client and server and because of that, can provide some advanced functionalities which are missing in older transports.

obfs3

obfs3 transport is supported but should generally be avoided in favor of obfs4.

obfs2

obfs2, the oldest transport is supported as well (mainly because its supported by obfs4proxy). You really shouldn’t use it…

Architecture

Before going into detail, its good to have a basic idea on how different parts of the script work together to provide obfs4 functionality to openvpn.

Client architecture

obfs4proxy-openvpn client diagram.png

  1. The script reads and validates its config file. This file is responsible for putting it in client mode as well as passing the required settings to it.
  2. The script does a basic check and validation on the specified openvpn config file. This file will be passed to the openvpn process later on.
  3. At this stage, obfs4proxy process is started acting as a SOCKS5 proxy server, listening to a random port.
  4. Based on its config, the script generates an appropriate socks5_auth file compatible with the openvpn.
  5. Using the specified openvpn config file, obfs4proxy local SOCKS5 port, and socks5_auth file, the execution is now passed to the openvpn client.
  6. openvpn client tries to connect to the remote server using the local obfs4proxy SOCKS5 proxy.
  7. obfs4proxy obfuscates the traffic and sends them along the line.

Server architecture

obfs4proxy-openvpn server diagram.png

  1. The script reads and validates its config file. This file is responsible for putting it in server mode as well as passing the required settings to it.
  2. The script does a basic check and validation on the specified openvpn config file. This file will be passed to the openvpn process later on.
  3. At this stage, obfs4proxy process is started. It binds to a valid IP address and port.
  4. Based on its config, the script starts openvpn server process, passing it the required port/address for binding (to receive traffic from obfs4proxy).
  5. obfs4proxy receives the obfuscated traffic from the internet and de-obfuscate it.
  6. The de-obfuscated traffic is passed to the openvpn server.

obfs4proxy-openvpn config

A sample config file is provided in the examples/ folder.

Please also note that this file (specially when used in client mode), will contain possibly sensitive data (i.e, the CERT). So better to set its permission to either 600 or 640:

chmod 600 /etc/obfs4proxy-openvpn.conf

Below are all the valid options along with a description for each (default values are placed inside parenthesis):

General options

These are options that are valid for both client and server:

  • MODE: mode of operation client/server.

  • TRANSPORT (obfs4): obfs4,obfs3 and obfs2 is supported.

  • OPENVPN_CONFIG_FILE: For maximum flexibility, the script does not magically generate an openvpn config file for you, and expects that you provide it with one instead. There are however almost ready-to-use openvpn config samples available in the repository which you may use.

  • OBFS4PROXY_WORKING_DIR (/var/lib/obfs4proxy-openvpn): The directory path that will be used for the obfsproxy log, config, as well as the socks5_auth file (in client mode). If the path does not exist, it will be automatically created by the script with the required permissions. It is possible to run multiple instance of the script by using different paths and config files.

  • OBFS4PROXY_UID / OBFS4PROXY_GID (obfs4-ovpn / obfs4-ovpn): The user and group name that obfs4proxy will run in. If neither UID nor GID already exist on the system (and their value matches), they will be automatically created by the script1. The home directory of the UID, will be set to OBFS4PROXY_WORKING_DIR. So I suggest that you use different set of UID/GID per each script instance2.

  • OBFS4PROXY_LOG_LEVEL (error): Can be one of none,error,warn,info,debug values which indicates the level of log for obfs4proxy.

  • OBFS4PROXY_LOG_IP (false): Should supposedly disable scrubbing addresses in the obfs4proxy log if its set to true3.

obfs4 specific options

These options are valid only when using obfs4 transport:

  • IAT_MODE (0): Inter-Arrival Time mode. Essentially this option provides some protections against packet timing fingerprints. Valid values are 0, 1 or 2. Client and server values don’t need to be matched. Do note that you would sacrifice some performance if enabled (specially if it’s set to 2).

Client options

These options are only valid when running in client mode and are ignored in server mode:

  • CLIENT_UPSTREAM_PROXY: The optional upstream proxy that obfs4proxy should use when making outgoing network connections. It is a URI [RFC3986] of the format:
<proxy_type>://[<user_name>[:<password>][@]<ip>:<port>

obfs4 specific client options

These options are only valid when the client using obfs4 transport:

  • CLIENT_REMOTE_CERT: This is a 70-characters long base64 string which must be imported from the obfs4proxy running on the server side. It’s basically a combination of CLIENT_REMOTE_NODE_ID and CLIENT_REMOTE_PUBLIC_KEY for maximum portability.

  • CLIENT_REMOTE_NODE_ID / CLIENT_REMOTE_PUBLIC_KEY: At its core, obfs4proxy uses these values for obfs4 transport. They can be directly specified instead of CLIENT_REMOTE_CERT. But you generally shouldn’t be needing to do that.

Server options

These options are only valid when running in server mode and are ignored in client mode:

  • SERVER_OBFS4_BIND_ADDR / SERVER_OBFS4_BIND_PORT (0.0.0.0 / 1516): This is the address:port that the obfs4proxy server would listen for incoming connections from obfs4proxy client (i.e, It is the same address:port that you should put in the --remote host [port] directive in openvpn client config file). Note that you may run into permission issues if you try to specify a port less than 10244.

  • SERVER_OPENVPN_BIND_ADDR / SERVER_OPENVPN_BIND_ADDR (127.0.0.1 / 1515): This is the address:port of the openvpn server that obfs4proxy server would redirect de-obfuscated traffic to. For this reason, the address is usually 127.0.0.1 to ensure real openvpn port is not accessible to the public. Another valid use is when the address is set to 0.0.0.0 making openvpn to bind to all interfaces. This could be beneficial and provides both obfuscated and non-obfuscated openvpn traffic at the same time.

OpenVPN configs

The script requires you to specify an openvpn config file. This is your typical openvpn client/server conf file in most aspects with couple of restrictions:

  • Only TCP tunneling is supported and no UDP specific option should be specified. You don’t need to explicitly set the --proto, this will be done by the script.
  • Don’t use --daemon or --inetd. You may however run obfs4proxy-openvpn as a service.
  • You may not use any related proxy options in client mode (e.g, --http-proxy, --socks-proxy). If you need to use a proxy to connect to the internet, it should be specified in CLIENT_UPSTREAM_PROXY.
  • You may not use --local,--port or --lport in server mode. These settings are adjusted via SERVER_OPENVPN_BIND_ADDR / SERVER_OPENVPN_BIND_ADDR.

OpenVPN UID/GID

You should consider running openvpn process in a limited (and preferably dedicated) account. The nobody UID should be available in most distros and it’s easy to use (but again, a better approach would be having a dedicated account for it).

This is more of an OpenVPN topic but it usually involves adding --user and --group directives in the openvpn config file along with --persist-tun and --persist-key to deal with any permission issues that might arise upon receiving SIGUSR1.

In client mode when using obfs4 transport, openvpn process also needs to access the socks5_auth file. For that reason, it is recommended that t uses the same group as obfs4proxy. This is not needed in server mode.

To recap, if you plan to run openvpn in a limited account (e.g, “nobody”), these would be the appropriate directives in the openvpn conf file:

In client mode:

user nobody
group obfs4-ovpn
persist-tun
persist-key

In server mode:

user nobody
persist-tun
persist-key

Hardcoded arguments

To make openvpn work with obfs4proxy, these hardcoded arguments are passed to it:

In client mode:

openvpn \
  --config $OPENVPN_CONFIG_FILE \
  --proto tcp-client \
  --socks-proxy 127.0.0.1 $CLIENT_OBFS4_SOCKS5_PORT $OBFS4PROXY_WORKING_DIR/socks5_auth

Note that CLIENT_OBFS4_SOCKS5_PORT will be generated by the obfs4proxy on each run and is not adjustable. $OBFS4PROXY_WORKING_DIR/socks5_auth is also only passed to the openvpn process when using obfs4 transport.

In server mode:

openvpn \
--config $OPENVPN_CONFIG_FILE \
--proto tcp-server \
--local $SERVER_OPENVPN_BIND_ADDR \
--lport $SERVER_OPENVPN_BIND_PORT

CIA triad

This section applies to obfs4 transport ONLY. In particular, it does NOT apply to obfs3/obfs2 transports.
DISCLAIMER: I’m not a cryptography expert. Do your own research first and do not blindly accept what you read on the internet.

Performance can be slightly improved by getting advantage of the obfs4 protocol encryption.

obfs4-spec suggests that the CIA triad concept applies obfs4 protocol as well. So If the CERT kept secret, one may rely on obfs4 alone for confidentiality, integrity and authenticity. In such cases, it might be okay to disable openvpn’s own encryption and authentication mechanisms (You do this by not including any --secret or tls related settings.

If the CERT is made publicly available, confidentiality and integrity are still kept but the client authenticity is lost. You have to rely on other means (like pre-shared secret keys or tls auth) to authenticate the clients. But it still might be okay to use --cipher none with it.

In both cases, openvpn should output a scary warning message about the situation.

If you have even the smallest doubt, just play it safe. It takes less than a second to setup a simple pre-shared key on the server:
openvpn --genkey --secret /etc/openvpn/secret.obfs4.key

and you’re not really reading this article to optimize OpenVPN throughput now, are you?!

obfs4proxy-openvpn arguments

The script comes with a limited support for command line arguments:

  • -h, --help: Outputs a simple help on the supported command line arguments.
  • -c, --config CONFIG_FILE: Points to obfs4proxy-openvpn config file that the script should employ. Default is /etc/obfs4proxy-openvpn.conf. One use for this is to run multiple instances of the script simultaneously. It’s also possible to use CONFIG_FILE alone as the only non-optional parameter.
  • --export-cert FILE: This option is only valid in server mode. The mandatory FILE argument is the path of a non-existent file to save the CERT string into (use - for stdout).
  • -V, --version: Outputs version number and copyright information.

Running as a service

After the execution is passed to it, openvpn process stays in the foreground until it ended (at that point the script will cleanup after itself and exit).

It’s possible to run the script as a service. A sample service file is provided in the examples/ folder. Download it and follow these simple steps to setup the service:

  1. Adjust the ExecStart line if required
  2. Move and rename to the correct location:
    mv examples/obfs4proxy-openvpn.service.sample /etc/systemd/system/obfs4proxy-openvpn.service
  3. Reload systemd configuration:
    systemctl daemon-reload
  4. Start the service:
    systemctl start obfs4proxy-openvpn.service
  5. Optionally check its status:
    systemctl status obfs4proxy-openvpn.service
  6. Enable the service at startup:
    systemctl enable obfs4proxy-openvpn.service

  1. Using adduser for Debian based distros and useradd for the rest. ↩︎

  2. You’d be able to delete the associated data just by deleting the user then. ↩︎

  3. If you could make that actually work, let me know! ↩︎

  4. An acceptable workaround for this is provided in my another post: How to hide (obfuscate) SSH traffic using obfs4

    from http://web.archive.org/web/20230516155711/https://hamy.io/post/000f/obfs4proxy-openvpn-obfuscating-openvpn-traffic-using-obfs4proxy/

    ------------------------------------------------------- 


关于obfsproxy的搭建,见 http://briteming.blogspot.co.uk/2012/12/obfsproxyshadowsocks-nodejs.html

https://github.com/edwardbarnard/udp_obfs (仅限于在linux desktop下使用)
(http://www.brokestream.com/udp_redirect.html)

https://www.torproject.org/projects/obfsproxy-instructions.html.en

http://sourceforge.net/mailarchive/forum.php?thread_name=510133EC.6000408%40topphemmelig.net&forum_name=openvpn-devel

---------------------

obfsproxy:模糊SSL或TLS加密流量的代理工具

据悉该工具目的是将SSL或TLS加密流量看起来像未加密的HTTP或即时通讯流量,从而突破封锁网络的国家对ssl加密通讯的封锁。目前该工具只能伪装SSL成SOCKS协议,未来将可以让加密流量伪装成任何协议。
Tor执行董事Andrew Lewman打了一个比方,该工具就像是在法拉利上套丰田外壳,让法拉利看起来像丰田。
obfsproxy通过数据流量在客户端与tor节点之间的转换来试图规避网络审查。这种方式的数据传输就像是“看起来无特征的”(innocent-looking)流量。
obfsproxy支持多种协议,称为可插拔传输(pluggable transports)。
obfsproxy是一个单独的应用程序,完全独立于Tor,它使用一个内部协议来尽量减少终端用户的配置。
官方项目主页:
https://www.torproject.org/projects/obfsproxy.html.en
https://www.torproject.org/dist/obfsproxy/
-----------------------------------------------------------

利用obfsproxy+OpenVPN进行翻墙


一种利用obfsproxy+OpenVPN进行翻墙的方式,目前情况下相当稳定快速。
obfsproxy 是 Tor Project 的一个附属项目,采用流量混淆的方式专门用于突破互联网封锁。对用户的表现形式是一个TCP端口转发隧道,和 ssh -L 的功能完全一致。

有任何建议和问题欢迎在Twitter上和我讨论: @blankwonder
本文目标读者为有一定Linux和网络知识基础的用户,并没有把所有命令全部傻瓜话的列出,

A. 服务器端配置

OpenVPN配置

首先,我们需要先安装配置OpenVPN,如果你不需要IPv6的话,直接用包管理安装就行。否则请到官网下载2.3版本的源码自行编译安装。(目前最新版本是2.3 RC2)
Debian编译OpenVPN所需要的包有libssl-dev, libpam0g-dev, liblzo2-dev
注:若是自行编译的OpenVPN,会缺少easy-rsa和init.d脚本,easy-rsa可以从OpenVPN官方的Github获得。init.d 脚本可以从各发行版的源码获得:
如果你没有修改安装prefix的话,OpenVPN会被安装到/usr/local/sbin/openvpn上,记得修改init.d脚本的相应内容。
接下来,按照标准的OpenVPN部署流程,生成各种密钥和证书(CA, server, client)。Linode 的官方文档写的非常好,这里不再阐述。
我使用的服务端配置(/etc/openvpn/openvpn.conf)如下:
local 127.0.0.1
port 40059
proto tcp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 172.16.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
duplicate-cn
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
log-append  /var/log/openvpn.log
verb 3
mute 10
由于我们需要使用obfsproxy进行二次混淆,所以这里让OpenVPN监听在127.0.0.1上。市面上的路由器默认的IPv4子网一般是 192.168.X.X或者10.X.X.X,这里为了避免和原有网络冲突,我选择了172.16.0.0/24作为VPN的子网。
接下来设置iptables进行NAT转换,这里省略了Linode文档中的安全部分(DROP),需要可自行补上。
sudo iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE
为了保证服务器重启后自动配置iptables,请需要将这条命令加入启动脚本
  • Debian/Ubuntu 用户:启动脚本的路径为 /etc/rc.local
  • Gentoo 用户:需要在/etc/local.d目录中创建一个后缀为.start的文件(如openvpn_iptables.start),将命令写在里面,同时记得使用chmod a+x。
接下来启动内核的IPv4转发
sudo sysctl -w net.ipv4.ip_forward=1
为了保证重启后不需要人工干预,在/etc/sysctl.conf中加入net.ipv4.ip_forward=1,这样重新启动后就不再需要sysctl -w了。
现在可以把OpenVPN跑起来了,命令如下
sudo /etc/init.d/openvpn start

obfsproxy配置

现在开始编译安装obfsproxy,官方指导文档在这 https://www.torproject.org/projects/obfsproxy-instructions.html.en
注:Gentoo用户在emerge libevent时请注意添加USE标记ssl。
Debian/Ubuntu用户可以直接使用包管理安装
sudo apt-get install obfsproxy
安装配置完毕后,启动obfsproxy,命令如下:
obfsproxy obfs2 --dest=127.0.0.1:40059 server 0.0.0.0:9132
请记得使用screen,nohup或daemon的方式运行obfsproxy。daemon当然最好,我比较懒就直接跑在screen里面了。
至此,服务端配置完毕。

B. 客户端配置

obfsproxy配置

首先编译安装obfsproxy,文档同上。
Mac用户可以用使用homebrew安装,请参照这里 https://github.com/mtigas/homebrew-tor/blob/master/README.md
由于我们需要将所有流量重定向到OpenVPN,而由于使用了obfsproxy,OpenVPN不知道服务器IP是多少没办法对到OpenVPN 服务器的流量进行特殊处理,所以我们需要手动将到服务器的路由固定下来,假设你的服务器IP为12.34.56.78,当前网络的网关地址是 192.168.1.1:(路由修改的命令请根据自己的操作系统自行调整,此处以Mac OS X为例)
sudo route add 12.34.56.78 192.168.1.1
完成了之后,开始运行obfsproxy
obfsproxy obfs2 --dest=12.34.56.78:9132 client 127.0.0.1:50443
如果是Mac用户,可以使用我的脚本,稍微简便一些(需要sudo)
#!/bin/bash

SERVER_IP="12.34.56.78"
GATEWAY=`netstat -nr | grep '^default' | grep -v 'tun' | sed 's/default *\([0-9\.]*\) .*/\1/'`

/sbin/route add $SERVER_IP $GATEWAY
/usr/local/bin/obfsproxy obfs2 --dest=${SERVER_IP}:9132 client 127.0.0.1:50443
# Below line won't be excuted until obfsproxy exit
/sbin/route delete $SERVER_IP $GATEWAY

OpenVPN配置

接下来选择你喜爱的OpenVPN客户端软件进行连接就可以了,我的配置式样例如下:
remote 127.0.0.1 50443 tcp-client
pull
tls-client
ns-cert-type server
persist-key
ca ca.crt
redirect-gateway def1
nobind
persist-tun
cert cert.crt
comp-lzo adaptive
dev tun
key key.key
dhcp-option DNS 8.8.8.8
resolv-retry infinite
log-append /var/log/openvpn.log
好的,现在你又可以尽情享受OpenVPN的全局翻墙了,如有需要可以结合 chnroutes 区分国内外流量进行选择性翻墙。
--------------------------------------------------------------

以obfsproxy解決中國2012年12月針對OpenVPN之網絡封鎖


【問題概況】
多得偉大團結無私的執政集團,以及曾入選中國網民眼中二十大嘔心人物的北京郵電大學方濱興校長,2012年12月,GFW針對OpenVPN進行網絡封 鎖,經一番追查和考究,最終發現封鎖技術建基於OpenVPN PKI模式下TLS Handshake過程的特徵。我們一直依賴OpenVPN突破網絡封鎖的國內人員亦深受影響,以我們一直的認知,以為OpenVPN並沒有特徵可言,但 事實是,TLS Handshake還是會有特徵
【應對方法】
解決方法1(消極):
「斬腳趾避沙蟲」,改用中古年代的Static-Key模式避過TLS Handshake過程,缺點是:
‧只能一個埠對應一個Client
‧一個Client就要有一個OpenVPN Instance
解決方法2(進取):
另一種比較進取的解決方法是要求OpenVPN社群建立為TLS Handshake過程進行加密的機制
透過TLS-Auth的Static-Key來進行,也是一個不錯的選擇
解決方法3(折騰):
以Obfsproxy模糊TLS Handshake過程,缺點是:
1. 效能上有小量Overhead
2. 不支援UDP…
3. Android手機似乎未有Obfsproxy客戶端…

以下是「解決方法3」的實作過程
【安裝obfsproxy】
#於伺服器和客戶端雙方安裝obfsproxy
$cd /usr/bin/
$sudo git clone https://git.torproject.org/obfsproxy.git
$cd obfsproxy
$./autogen.sh && ./configure && make
$sudo make install
#視窗用戶可下載Windows Obfsproxy Tor Browser Bundle
#https://www.torproject.org/dist/torbrowser/tor-obfsproxy-browser-2.4.6-alpha-2_en-US.exe
【伺服器obfs 設置】
$sudo obfsproxy –log-min-severity=info obfs2 –shared-secret=”Neverf0rget8964″ –dest=127.0.0.1:1194 server 0.0.0.0:689
#基於Obfsproxy限制,OpenVPN 伺服器所用的1194埠是指TCP1194,而非UDP1194
【客戶端obfs 設置】
$obfsproxy –log-min-severity=info obfs2 –shared-secret=”Neverf0rget8964″ socks 127.0.0.1:689
【伺服器Sample Init Script】
#! /bin/sh
### BEGIN INIT INFO
#Provides: ObfsProxy Init Script for OpenVPN
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: Fuck GFW
# Description: ObfsProxy Daemon for OpenVPN
### END INIT INFO
PIDFILE=/var/run/obfsproxy.pid
PATH=/usr/bin:/sbin
DESC=”ObfsProxy Daemon for OpenVPN”
NAME=obfsproxy
DAEMON=/usr/bin/obfsproxy/obfsproxy
DAEMON_ARGS=”–log-min-severity=info obfs2 –shared-secret=Neverf0rget8964 –dest=127.0.0.1:8080 server 0.0.0.0:689″
TIMEOUT=30
SCRIPTNAME=/etc/init.d/obfsproxy
case “$1″ in start)
echo -n “Starting ObfsProxy Daemon for OpenVPN”
start-stop-daemon -b –start –quiet –make-pidfile –pidfile $PIDFILE –exec $DAEMON — $DAEMON_ARGS
;;
stop)
echo -n “Shutting down ObfsProxy Daemon for OpenVPN”
start-stop-daemon –stop –quiet –retry=QUIT/$TIMEOUT/TERM/5/KILL/5 –pidfile $PIDFILE –name $NAME
;;
esac
【客戶端ovpn 更改】
-remote openvpnserver.com 1194
+remote openvpnserver.com 689
+socks-proxy 127.0.0.1 689
【NAT】
伺服器端無須再就TCP 1194進行Static PAT,相反TCP 689要做NAT Mapping。
【結論】
方校長這次還玩得真有點過火
原文连接:https://www.facebook.com/notes/%E6%AF%8B%E5%BF%98%E5%85%AD%E5%9B %9B/%E7%B6%B2%E7%B5%A1%E8%A1%8C%E5%8B%95%E7%B5%84-%E4%BB%A5obfsproxy%E8%A7%A3%E6%B1%BA%E4%B8%AD%E5%9C%8B2012%E5%B9%B412%E6%9C%88%E9%87%9D%E5%B0%8Dopenvpn%E4%B9%8B%E7%B6%B2%E7%B5%A1%E5%B0%81%E9%8E%96%E5%A2%9E%E5%BC%B7/10150993099683078
------------


使用OpenVPN+obfsproxy翻墙


本文向您展示如何通过OpenVPN发送您的PC流量,您的OpenVPN流量被Obfsproxy伪装。 OpenVPN在端口1194上进行通信,无需伪装,因为它的流量将通过非标准端口上的Obfsproxy进行代理。 出于本教程的目的,我们为Obfsproxy选择了端口51194。
此示例中的服务器运行Debian 9,客户端是运行Windows 10的PC.Debian 9提供OpenVPN版本2.4,其中包括加密OpenVPN控制通道的新功能。 Debian 9中包含的Linux内核还提供BBR拥塞控制。

服务器

请按以下步骤继续操作。

Obfsproxy

在Debian服务器上安装Obfsproxy:
sudo apt-get install obfsproxy
打开防火墙端口51194,以便流量可以到达Obfsproxy。
sudo iptables -A INPUT -p tcp --dport 51194 -j ACCEPT

sudo dpkg-reconfigure iptables-persistent
(为了更好地防止主动探测和重放攻击,请考虑将可以向您的OpenVPN + Obfsproxy服务器发送流量的IP地址列入白名单的可能性。例如,假设您的ISP始终在12.34.0.0范围内为您分配IP地址12.34.255.255 ,在无类别域间路由表示法中为12.34.0.0/16 。考虑使用-s 12.34.0.0/16来进一步限制iptables规则。)
为Obfsproxy启动单独的屏幕过程:
screen -S obfsproxy
调用obfsproxy,向OpenVPN服务器发送任何有效流量,我们将很快在localhost端口1194上设置,并监听TCP端口51194上的输入:
sudo obfsproxy --log-file=obfsproxy.log --log-min-severity=info obfs3 --dest=127.0.0.1:1194 server 0.0.0.0:51194
这是一个长命令。
要从obfsproxy开始的屏幕处理中分离,请立即按Ctrl + a ,然后按键盘上的d键。
(每当您想要重新连接该屏幕进程时,请发出命令screen -r obfsproxy 。要从屏幕进程中screen -r obfsproxy正在运行的命令,请执行Ctrl + C.要完全结束屏幕进程,请使用exit命令。)

OpenVPN的

以root身份执行此处的步骤最简单。 如果您不知道root密码,请先通过sudo passwd root设置它。
切换到root用户:
su -
在Ubuntu服务器上安装OpenVPN和Easy-RSA。 Easy-RSA是一组脚本,它们调用OpenSSL来构建和管理OpenVPN的公钥基础结构(PKI)。
apt-get install openvpn easy-rsa
将Easy-RSA脚本复制到OpenVPN目录中,然后切换到包含副本的目录:
cp -r /usr/share/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa
我的Debian 9系统出现了问题,因为在whichopensslcnf脚本中不允许使用OpenSSL 1.1.0版本。 它产生了一条错误消息, No /openssl.cnf file could be found 。 为了防止这个错误,我不得不发出命令:
cp openssl-1.0.0.cnf openssl.cnf
编辑变量文件:
vi vars
将变量设置为所需的值:
# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"
如有必要,按键盘上的Esc键退出插入模式。 键入:wq将文件写入磁盘并退出编辑器。
从文件中的值设置环境变量:
source ./vars
删除以前创建的所有密钥和证书:
./clean-all
生成证书颁发机构(CA)证书:
./build-ca
系统将要求您输入要在证书中输入的值。 如果按Enter键 ,证书将获取您在vars文件中指定的值。
生成服务器密钥。 在下面的示例中,服务器称为138.68.78.88 。 替换为您的真实主机名或IP地址,或您希望为OpenVPN服务器提供的任何名称。
./build-key-server 138.68.78.88
请勿输入质询密码或公司名称。
签署证书( y ),然后提交( y )。
脚本运行后,您的keys目录将包含名为(继续此示例) 138.68.78.88.key , 138.68.78.88.csr和138.68.78.88.crt 。
为客户端生成密钥和证书。 在此示例中,只有一个客户端,它名为client1 。
./build-key client1
请勿输入质询密码或公司名称。
签署证书( y ),然后提交( y )。
生成用于加密的Diffie-Hellman参数:
./build-dh
这将需要很长时间。 完成此过程后,将相关文件复制到主/etc/openvpn目录中:
cp keys/*.key ..
cp keys/*.crt ..
cp keys/dh2048.pem ..
还要创建tls-crypt密钥,它将用于加密控制信道通信:
cd ..
openvpn --genkey --secret tls-crypt.key
复制并解压缩示例服务器配置文件:
cd /usr/share/doc/openvpn/examples/sample-config-files
cp server.conf.gz /etc/openvpn
cd /etc/openvpn
gzip -d server.conf.gz
这将创建一个名为server.conf的文件。 编辑此文件:
vi server.conf
更改为TCP:
proto tcp
;proto udp
更改为实际证书和密钥名称:
cert 138.68.78.88.crt
key 138.68.78.88.key # This file should be kept secret
(当然,您必须将138.68.78.88替换为您的实际服务器IP地址。)
取消注释(即从中删除初始分号):
push "redirect-gateway def1 bypass-dhcp"
取消注释将DNS服务器推送到Windows客户端的行:
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
指定tls-crypt密钥:
;tls-auth ta.key 0 # This file is secret
tls-crypt tls-crypt.key
指定一个强密码:
cipher AES-256-GCM
没有压缩:
;comp-lzo
没有明确的退出通知:
;explicit-exit-notify 1
按键盘上的Esc退出插入模式,然后键入:wq将文件写入磁盘并退出编辑器。
允许在Linux内核中转发:
vi /etc/sysctl.conf
取消注释该行:
net.ipv4.ip_forward=1
还要添加以下两行以指定BBR拥塞控制。 BBR拥塞控制在Linux内核4.9中可用,例如在Debian 9中。
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
按键盘上的Esc退出插入模式,然后键入:wq将文件写入磁盘并退出编辑器。
立即激活这些更改:
sysctl -p
转发传入数据包:
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE

dpkg-reconfigure iptables-persistent
应用所有这些更改重新启动OpenVPN:
systemctl enable openvpn@server

systemctl start openvpn@server
检查一切是否正常:
journalctl -u openvpn@server
tail /var/log/syslog
netstat -tulpn | grep openvpn
如果您的系统中未包含netstat ,请改用ss 。 它应该显示OpenVPN侦听端口1194。

Client1配置文件

在我们的客户端Windows PC上安装OpenVPN之前,我们将为我们的第一个客户端制作配置文件,我们在这里命名为client1。 即使我们准备在Windows PC上使用此文件,我们也将在Debian服务器上构建该文件。
从示例配置文件开始,复制它,并将其重命名为client1.ovpn :
cd /usr/share/doc/openvpn/examples/sample-config-files
cp client.conf /etc/openvpn/client1.ovpn
cd /etc/openvpn/
vi client1.ovpn
更改为TCP:
proto tcp
;proto udp
填写远程服务器IP地址。 请注意,我们的目标是端口51194,Obfsproxy正在监听:
remote 138.68.78.88 51194
(当然,您必须将138.68.78.88替换为您的实际服务器IP地址。)
我们将在ovpn文件中嵌入CA证书,客户端证书,客户端密钥和tls-crypt密钥。 使用内联文件如下所示:
<ca>
-----BEGIN CERTIFICATE-----
MIIF...
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIIF...
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----
</key>
<tls-crypt>
-----BEGIN OpenVPN Static key V1-----
bc43...
-----END OpenVPN Static key V1-----
</tls-crypt>
在vi编辑器中,您可以通过将光标定位到您想要插入的内容的位置来读取文件,依次为三个文件中的每个文件,并依次执行:
:r ca.crt
:r client1.crt
:r client1.key
:r tls-crypt.key
在读入这些文件时删除任何不必要的行。
注释掉tls-auth行:
;tls-auth ta.key 1
指定一个强密码:
cipher AES-256-GCM
没有压缩:
;comp-lzo
添加以下行:
socks-proxy-retry
socks-proxy 127.0.0.1 1080
这告诉OpenVPN将其流量发送到localhost上的SOCKS代理服务器,我们将设置为侦听端口1080。
按键盘上的Esc退出插入模式,然后键入:wq将文件写入磁盘并退出编辑器。
那是现在服务器工作的结束。 退出根会话,退出SSH会话。
exit
exit

客户机器。

Python 2.7

在PC的浏览器中,访问https://www.python.org/downloads/windows/ 。
假设您有64位Windows PC,请下载最新版本的Python 2.7.x系列的64位MSI安装程序。
双击安装程序以启动它。
为所有用户安装到文件夹C:\Python27\ 。 这可能会需要几分钟。

用于Python 2.7的Microsoft C ++编译器

在PC的浏览器中,访问https://www.microsoft.com/en-us/download/details.aspx?id=44266 。
下载文件VCForPython27.msi 。
双击安装程序以启动它。
选中此复选框即表示您接受许可协议中的条款。单击安装 

OpenSSL Light

在PC的浏览器中,访问https://slproweb.com/products/Win32OpenSSL.html 。
下载文件Win32OpenSSL_Light-1_1_0f.exe 。 这将安装Win32 OpenSSL v1.1.0f最常用的必需品(由OpenSSL的创建者推荐给用户)。
双击安装程序以启动它。按照提示安装OpenSSL Light。

Obfsproxy

按PC键盘上的Windows键,搜索cmd ,右键单击它,然后选择以管理员身份运行 。
转到将安装Obfsproxy的目录:
cd C:\Python27\Scripts
安装Obfsproxy Python包:
pip install obfsproxy
安装完成后,您将返回到C:\Python27\Scripts>命令提示符。
启动Obfsproxy作为侦听端口1080的SOCKS代理服务器:
obfsproxy --log-min-severity=info --log-file=obfsproxy.log obfs3 socks 127.0.0.1:1080
只要您需要运行Obfsproxy,就让命令窗口保持打开状态。

安装PuTTY时,您还应该安装PuTTY安全副本( pscp.exe )实用程序。 我们现在将使用该实用程序从服务器安全地检索client1.ovpn文件。
在Windows PC上,打开另一个命令提示符。 这个不需要以管理员身份运行。 在命令窗口中,发出命令:
cd C:\Program Files\PuTTY

pscp derek@138.68.78.88:/etc/openvpn/client1.ovpn C:\Users\derek\Downloads\client1.ovpn
第二行有一个长命令。 当然,您必须在此命令中使用您自己的用户ID和IP地址替换用户ID derek和IP地址138.68.78.88 。
下载完成后,您可以关闭第二个命令窗口。 保持命令窗口中的Obfsproxy在其中运行。
从以下位置下载Windows版OpenVPN的安装程序:
https://openvpn.net/index.php/open-source/downloads.html
安装程序将具有诸如openvpn-install-2.4.3-I602.exe 。 下载安装程序后,右键单击它,然后选择以管理员身份运行 。
允许安装程序运行,接受其默认建议。 运行后,单击“ 完成” 。
安装程序在桌面上创建OpenVPN GUI图标。
右键单击OpenVPN GUI图标,然后选择以管理员身份运行 。
OpenVPN GUI保留在系统托盘中(右下角)。 您必须右键单击它才能打开菜单。 选择导入文件….
从Downloads文件夹中选择文件client1.ovpn ,然后单击Open 。
您应该收到一条消息,说明该文件已成功导入。
仔细检查Obfsproxy客户端是否仍在其命令窗口中运行。
现在,右键单击系统托盘中的OpenVPN图标,这次选择“ 连接” 。
连接发生时显示状态消息。 如果您需要稍后再次查看这些消息,可以单击OpenVPN菜单中的查看日志 。
您已连接到OpenVPN服务器,并通过Obfsproxy代理流量.
----------

相关帖子:https://briteming.blogspot.com/2017/11/obfsproxy-openvpn.html
----------------------------------------------------------------------------------------------------

How to obfuscate any traffic using obfs4

Overview

In this post, I’m going to give you the information necessary to be able to use obfs4 protocol not just for wrapping Tor traffic, but for virtually any other TCP traffic as well.

Doing so for the previous Pluggable Transports of this kind (namely obfs2,obfs3 and ScrambleSuit) was rather simple. obfsproxy program written python, already supports being run in standalone (or so called unmanaged) mode and there are dozens of guides available on how to do so.

However, obfs4proxy which implements obfs4 protocol in Go, is primarily designed to work in conjunction with Tor (managed mode). This is not a protocol limitation but rather an implementation one.

If you ever try running obfs4proxy by itself, you’d get an error like this:

[ERROR]: obfs4proxy - must be run as a managed transport

But Hey! It is not the end of the world. There are still couple of ways to make use of obfs4 outside of Tor:

  • Adding unmanaged mode of operation to obfs4proxy
    This is probably the best way, but I’m not a Go programmer so I’ll leave that to those who are.

  • Using external wrappers
    PTProxy and ptadapter in Python, along with Shapeshifter in Go, are just some of the options available.

  • Make your own script to bootstrap the launch of obfs4proxy
    This is the main interest of this article: showing you how to do so without relying on third party apps.

While I will primarily target Linux, it should be possible to apply the same procedures to other operating systems (e.g, Windows) as well.

Overall setup

Before going into details, it’s good to have a basic understanding of the process involved. Let’s take a look at the architecture:

 

  • Client App
    Is the program on the client side that you want to wrap its traffic with obfs4.

  • obfs4proxy Client
    obfs4proxy exposes a SOCKS5 proxy for the client app to connect to. The client app should be set to use the local obfs4proxy SOCKS5 capability to connect to the obfs4proxy server.
    Apart form some special environment variables (which needs to be set), a so called cert (which needs to be imported from obfs4proxy server) and iat-mode has to be passed to obfs4proxy client via SOCKS5 authentication fields.

  • Server App
    The final destination that your client app’s traffic would be redirected to.

  • obfs4proxy Server
    On the server, obfs4proxy gets almost all of its settings via special environment variables. Including the address:port it should listen to, as well as the ones it should forward the de-obfuscated traffic to (server app’s address:port).
    Upon the first start, it also generates a node-id and a public-key and makes a cert out of them. This cert is needs to be used by the client.

Requirements and Limitations

  • obfs4proxy program
    Either compile it from source code or use your distro’s repository.

  • SOCKS5 with authentication support by your client app
    Obviously your app will be running in client/server mode. On the client side, obfs4proxy exposes a SOCKS5 port for the client app to send its data to. While most decent programs should support SOCKS5 (either natively or via environment variables), If yours doesn’t, you must find a way to socksify it first.

  • Client/Server app must use TCP
    This one is a quite unfair limitation. There should be no technical reasons why obfs4 couldn’t forward UDP traffic through SOCKS5. And in fact, it would help quite tremendously being able to use them in UDP mode if they support it.

Environment variables

Beside some basic command line options, obfs4proxy relies on environment variable for its startup.

Some of these environment variables are mandatory, some optional, and some are either client or server specific.

The way of setting environment variables differ with operating systems. Search the web to find the proper way of doing so for your OS.

For example in Linux, it is possible to pass environment variables to a program by using:

env VAR1="value1" VAR2="value2"... path_to_the_executable

We will now examine all the environment variables that are being used by obfs4proxy. Those in red are mandatory while the rest are optional.

Common environment variables

As the name suggests, these are used by both obfs4proxy client and server:

  • TOR_PT_MANAGED_TRANSPORT_VER
    The version of PT in use. It must be “1”.

  • TOR_PT_STATE_LOCATION
    Basically the working directory for obfs4proxy. It must be writable by the user obfs4proxy is running as.
    At the moment, this directory may host 3 different files:

    • obfs4proxy.log - Log file (if it’s enabled)
    • obfs4_state.json - obfs4proxy server config
    • obfs4_bridgeline.txt - A helper file containing the line needed for importing to Tor clients
  • TOR_PT_EXIT_ON_STDIN_CLOSE
    If it’s set to “1”, closing stdin would signal obfs4proxy to gracefully exit.

Server environment variables

  • TOR_PT_SERVER_TRANSPORTS
    While obfs4proxy has some limited backward compatibility support for older protocols, we are only interested in “obfs4”.

  • TOR_PT_SERVER_TRANSPORT_OPTIONS
    As far I know, the only use for this in obfs4, is specifying an iat-mode other than 0. The correct format is “obfs4:iat-mode=1” or “obfs4:iat-mode=2”

  • TOR_PT_SERVER_BINDADDR
    The local address that obfs4proxy should bind to. The format is obfs4-local_ip:port for example “obfs4-0.0.0.0:2222”

  • TOR_PT_ORPORT
    The address:port destination that the obfs4proxy server instance should forward the incoming traffic to after de-obfuscation. This is usually the port of your server app bound to the localhost. For example “127.0.0.1:22”.

  • TOR_PT_EXTENDED_SERVER_PORT
    The Extended ORPort protocol. According to the spec, It…

    allows the PT reverse proxy to communicate per-connection metadata such as the PT name and client IP address/port to the parent process.

  • TOR_PT_AUTH_COOKIE_FILE
    This is a mandatory option incase TOR_PT_EXTENDED_SERVER_PORT is specified. It is for specifying…

    an absolute filesystem path to the Extended ORPort authentication cookie, required to communicate with the Extended ORPort.

TOR_PT_EXTENDED_SERVER_PORT and TOR_PT_AUTH_COOKIE_FILE are not needed in our use case.

Client environment variables

  • TOR_PT_CLIENT_TRANSPORTS
    While obfs4proxy has some limited backward compatibility support for older protocols, we are only interested in “obfs4”.

  • TOR_PT_PROXY
    If the client is behind a firewall (or otherwise must use a proxy server), the upstream proxy is set here. The format is:
    <proxy_type>://[<user_name>[:<password>][@]<ip>:<port>

Command line options

While most settings needs to be set via environment variables, obfs4proxy supports some basic optional command line arguments:

  • -enableLogging
    Logs to TOR_PT_STATE_LOCATION/obfs4proxy.log . Rather handy for debugging.

  • -logLevel ERROR|WARN|INFO|DEBUG
    Default is ERROR.

  • -unsafeLogging
    Should disable scrubbing addresses in the log. I couldn’t make it work however.

  • -obfs4-distBias
    Controls if the probability table will be ScrambleSuit style or uniformly distributed.

  • -version
    Comes from the Greek word “εκδοχή”, it hijacks the current process.
    Just kidding, will output the version number and exit.

The procedure

Once you know how to set things up, it becomes pretty easy to make it work:

On the server

  1. You preferably setup server app to listen to localhost only. This is to avoid exposing the un-obfuscated port to the public.
  2. Passing the required environment variables, You run obfs4proxy server. This would give you the cert and also start listening for new connections.

On the client

  1. Passing the required environment variables, you run obfs4proxy client. obfs4proxy would setup a SOCKS5 server on a random local port (which it announces).
  2. You set your client app to connect to the server app using the provided SOCKS5 proxy offered by obfs4proxy client.

The second step requires a little bit more explanation:

obfs4proxy client expects some of its arguments (namely the cert of the remote server as well as the iat-mode), to be provided via SOCKS5 authentication fields.

According the pt-spec, the format of the fields in our case, should be as follows:

UNAME : cert=<cert>;iat-mode=<iat-mode>
PASSWD: <NUL char>

However, specifying a null character in our client app as the password, could be tricky.

Even though it might be theoretically against pt-spec7, expanding part of our arguments to the PASSWD field, works:

UNAME : cert=<cert>;iat-mode=
PASSWD: <iat-mode>

And that’s it!

To see a real world example of this, take a look at my next post:
How to hide (obfuscate) SSH traffic using obfs4

I would love to hear your thoughts about this article. Please leave a comment below and let me know.


  1. Taken from pt-spec-v1

  2. Inter-Arrival Time mode used to defeat dpi fingerprints based on timing. The setting does not need to be same on the client and server and can be adjusted independently. 

  3. So in theory, it should be possible to use the same obfs4proxy client process to simultaneously connect to different obfs4proxy servers, each with their own set of certs and iat-modes. 

  4. This package is available with the same name in Debian/Ubuntu. For Windows, compiled binary can be extracted from the Tor Browser

  5. archlinux wiki is a good place to get more info on this for Linux.

  6. Also take a look at OpenVPN - TCP or UDP tunneling

  7. Expanding the encoded argument list to the PASSWD filed is only allowed when the length is more than 255 bytes. 

    from https://hamy.io/post/000d/how-to-hide-obfuscate-any-traffic-using-obfs4/ 

    http://web.archive.org/web/20240724035211/https://hamy.io/post/000d/how-to-hide-obfuscate-any-traffic-using-obfs4/

    --------------------------------