trojan-gfw / trojan Goto Github PK
View Code? Open in Web Editor NEWAn unidentifiable mechanism that helps you bypass GFW.
Home Page: https://trojan-gfw.github.io/trojan/
License: GNU General Public License v3.0
An unidentifiable mechanism that helps you bypass GFW.
Home Page: https://trojan-gfw.github.io/trojan/
License: GNU General Public License v3.0
"ssl": {
"cert": ""
},
only supports external file(file directory), it will be good if trojan can support certs in the configure file, like
"cert": [
"-----BEGIN CERTIFICATE-----",
"exampleCert",
"-----END CERTIFICATE-----"
],
I ran a server using certificate issued by Let's Encrypt. And I cannot connect to the server. I always got "SSL handshake failed with ..." error.
Server config:
{
"run_type": "server",
"local_addr": "0.0.0.0",
"local_port": 443,
"remote_addr": "127.0.0.1",
"remote_port": 80,
"password": ["12345678"],
"log_level": 3,
"ssl": {
"cert": "/root/.acme.sh/example.com/fullchain.cer",
"key": "/root/.acme.sh/example.com/example.com.key",
"key_password": "",
"cipher": "ECDHE-RSA-AES128-GCM-SHA256",
"prefer_server_cipher": true,
"alpn": ["http/1.1"],
"reuse_session": true,
"session_timeout": 300,
"curves": "brainpoolP256r1",
"sigalgs": "",
"dhparam": ""
}
}
Client config:
{
"run_type": "client",
"local_addr": "127.0.0.1",
"local_port": 1082,
"remote_addr": "example.com",
"remote_port": 443,
"password": ["12345678"],
"log_level": 1,
"ssl": {
"verify": true,
"verify_hostname": true,
"cert": "LetsEncrypt-CA.txt",
"cipher": "ECDHE-RSA-AES128-GCM-SHA256",
"sni": "example.com",
"alpn": ["http/1.1"],
"reuse_session": true,
"curves": "brainpoolP256r1",
"sigalgs": ""
}
}
GnuTLS has some nice features which could help circumventing GFW. GnuTLS does hide record lengths and can be configured to emulate OpenSSL signatures, and therefore could be useful against TLS over TLS detections and other attacks.
One caveat: GnuTLS is considered to be lacking in security reviews.
Certificate Problem.
A self-signed or a not well-known certificate can be simply put into suspected list by GFW.
Anti-Passive Detection will not work.
Data chunks are wrapped into Application Data which has only a fixed-length header(0x170303 + 2 bytes chunk_len), thus the feature of application traffic cannot be obfuscated by your protocol.
Is there any plan to create a decentralised version in order to democratize the tool similar to privatix.io? I personally think anti censorship tools should be used by everyone and there are very good platform like v2ray but the issue being only a very small population will use it eventually eg. 100k vs 1b potential users. If there are many proxy nodes run by international community and they are incentivised to do so, it would be hard for gfw to block them all. From a technical standpoint, most coders focus on the technical aspect of being stealthy but for users, it is about costs and availability. A decentralised business model is probably more conducive to mass adoption than being just an incremental improvement in stealth.
同443端口,使用letsencrypt生成的证书。
选择不使用ssl,能正常连接:
"ssl_verify":false,
"ssl_verify_hostname":false
使用ssl验证,报错SSL handshake failed with xxx.xx
TLS1.3 has a lot of security and performance improvements such as 0-RTT, and HKDF. Please consider implement TLS1.3 for hardened security.
平常习惯于路由器,系统是OpenWRT,希望有开源代码可以编译成为ipk文件,以便装载到路由器上
左边是caddy.forwardproxy 右边是trojan
trojan延时高些
httping测试 $httping -g http://google.com --proxy 127.0.0.1:1001 -Y -c 100
同时、同服务器haproxy复用443端口sni分流、都是tls1.3(winshark抓包)
配置是按examples写的,尝试修改"append_payload": false "session_ticket": true 均无改善
连接方式:
httping→privoxy→trojan(client)→trojan(server)→internet
httping→caddy.forwardproxy(http→upstream)→caddy(server)→internet
[FATAL] trojan service (server) started at 0.0.0.0:443
Doesn't look fatal to me.
$ cmake .. && make
-- The C compiler identification is GNU 7.2.1
-- The CXX compiler identification is GNU 7.2.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE
-- Boost version: 1.66.0
-- Found the following Boost libraries:
-- atomic
-- chrono
-- date_time
-- system
-- thread
-- Found OpenSSL: /usr/lib/libcrypto.so (found suitable version "1.1.0g", minimum required is "1.0.2")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/src/troj/trojan/build
Scanning dependencies of target trojan
[ 9%] Building CXX object CMakeFiles/trojan.dir/src/clientsession.cpp.o
In file included from /home/user/src/troj/trojan/src/clientsession.h:23:0,
from /home/user/src/troj/trojan/src/clientsession.cpp:20:
/home/user/src/troj/trojan/src/session.h:43:74: error: 'stream_socket_service' is not a member of 'boost::asio'
virtual boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket() = 0;
^~~~~~~~~~~~~~~~~~~~~
/home/user/src/troj/trojan/src/session.h:43:74: note: suggested alternative: 'make_service'
virtual boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket() = 0;
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/session.h:43:74: error: 'stream_socket_service' is not a member of 'boost::asio'
/home/user/src/troj/trojan/src/session.h:43:74: note: suggested alternative: 'make_service'
virtual boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket() = 0;
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/session.h:43:116: error: wrong number of template arguments (2, should be 1)
t::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket() = 0;
^
In file included from /usr/include/boost/asio/basic_datagram_socket.hpp:20:0,
from /usr/include/boost/asio.hpp:23,
from /home/user/src/troj/trojan/src/session.h:26,
from /home/user/src/troj/trojan/src/clientsession.h:23,
from /home/user/src/troj/trojan/src/clientsession.cpp:20:
/usr/include/boost/asio/basic_socket.hpp:60:7: note: provided for 'template<class Protocol> class boost::asio::basic_socket'
class basic_socket
^~~~~~~~~~~~
In file included from /home/user/src/troj/trojan/src/clientsession.h:23:0,
from /home/user/src/troj/trojan/src/clientsession.cpp:20:
/home/user/src/troj/trojan/src/session.h:43:118: error: expected unqualified-id before '>' token
:asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket() = 0;
^
In file included from /home/user/src/troj/trojan/src/clientsession.cpp:20:0:
/home/user/src/troj/trojan/src/clientsession.h:53:66: error: 'stream_socket_service' is not a member of 'boost::asio'
boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket();
^~~~~~~~~~~~~~~~~~~~~
/home/user/src/troj/trojan/src/clientsession.h:53:66: note: suggested alternative:
make_service'
boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket();
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/clientsession.h:53:66: error: 'stream_socket_service' is not a member of 'boost::asio'
/home/user/src/troj/trojan/src/clientsession.h:53:66: note: suggested alternative:
make_service'
boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket();
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/clientsession.h:53:108: error: wrong number of template arguments (2, should be 1)
t::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket();
^
In file included from /usr/include/boost/asio/basic_datagram_socket.hpp:20:0,
from /usr/include/boost/asio.hpp:23,
from /home/user/src/troj/trojan/src/session.h:26,
from /home/user/src/troj/trojan/src/clientsession.h:23,
from /home/user/src/troj/trojan/src/clientsession.cpp:20:
/usr/include/boost/asio/basic_socket.hpp:60:7: note: provided for 'template<class Protocol> class boost::asio::basic_socket'
class basic_socket
^~~~~~~~~~~~
In file included from /home/user/src/troj/trojan/src/clientsession.cpp:20:0:
/home/user/src/troj/trojan/src/clientsession.h:53:110: error: expected unqualified-id before '>' token
:asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >& accept_socket();
^
/home/user/src/troj/trojan/src/clientsession.cpp:39:45: error: 'stream_socket_service' is not a member of 'boost::asio'
boost::asio::basic_socket<tcp, boost::asio::stream_socket_service<tcp> >& ClientSession::accept_socket() {
^~~~~~~~~~~~~~~~~~~~~
/home/user/src/troj/trojan/src/clientsession.cpp:39:45: note: suggested alternative: 'make_service'
boost::asio::basic_socket<tcp, boost::asio::stream_socket_service<tcp> >& ClientSession::accept_socket() {
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/clientsession.cpp:39:45: error: 'stream_socket_service' is not a member of 'boost::asio'
/home/user/src/troj/trojan/src/clientsession.cpp:39:45: note: suggested alternative: 'make_service'
boost::asio::basic_socket<tcp, boost::asio::stream_socket_service<tcp> >& ClientSession::accept_socket() {
^~~~~~~~~~~~~~~~~~~~~
make_service
/home/user/src/troj/trojan/src/clientsession.cpp:39:70: error: wrong number of template arguments (2, should be 1)
boost::asio::basic_socket<tcp, boost::asio::stream_socket_service<tcp> >& ClientSession::accept_socket() {
^
In file included from /usr/include/boost/asio/basic_datagram_socket.hpp:20:0,
from /usr/include/boost/asio.hpp:23,
from /home/user/src/troj/trojan/src/session.h:26,
from /home/user/src/troj/trojan/src/clientsession.h:23,
from /home/user/src/troj/trojan/src/clientsession.cpp:20:
/usr/include/boost/asio/basic_socket.hpp:60:7: note: provided for 'template<class Protocol> class boost::asio::basic_socket'
class basic_socket
^~~~~~~~~~~~
/home/user/src/troj/trojan/src/clientsession.cpp:39:72: error: expected unqualified-id before '>' token
boost::asio::basic_socket<tcp, boost::asio::stream_socket_service<tcp> >& ClientSession::accept_socket() {
^
make[2]: *** [CMakeFiles/trojan.dir/build.make:63: CMakeFiles/trojan.dir/src/clientsession.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/trojan.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
Trojan version 1.9.0 on both server and client.
I can't get Trojan to send any data, all connections to the local proxy running on 127.0.0.1:1080 fail with "unknown protocol". No output appears on the server's end.
If it matters at all, the server is running in a FreeBSD jail behind a reverse proxy, all traffic is routed host -> reverse-proxy -> jail.
Ask for official docker image support.
Build and Install
Type in
mkdir build
cd build/
cmake ..
make
ctest
sudo make install
root@11:~/trojan/build# make install
make: *** No rule to make target 'install'. Stop.
Hi,
I have a question about this project:
Does TLS over TLS make it more easy for GFW to detect such 'hidden' traffic?
We already know that GFW can detect and interfere the OpenVPN traffic very quickly.
Ref:
https://gist.github.com/micooz/52a81852e3f6d1614f66e07b0757cd6c
https://gist.github.com/clowwindy/5947691
http://jiji.io/p/12699180487511941578
Is the TLS stack used here being audited for fingerprinting potential?
我应该如何与CDN结合使用?
Add .service for trojan server and client.
When I connect my own server with client, it will show these error infos.
server:
client:
I set cert.pem
for cert, privkey.pem
for key and keep empty for key password in my server's configuration file, which are provided by Let's Encrypt. And I also set cert.pem
for cert in my client's configuration file.
I don't know if I choose a wrong certificate, and when I choose fullchain.pem
, these error infos disappeared again.
Trojan died after a while.
@UzminTid Thank you for your contributions to the Trojan wiki. Communication languages other than English are strongly discouraged in this organization, so I reverted your changes (Chinese translation) in the wiki. I encourage you to host a repository yourself if you still want to present Chinese wiki. To retrieve your files, you can execute the following commands:
git clone https://github.com/trojan-gfw/trojan.wiki.git
cd trojan.wiki
git checkout 3ff96b7
Please consider adding PSK cipher suites for certificate-less setup.
Recommendation:
TLS_PSK_WITH_AES_128_GCM_SHA256 and TLS_PSK_WITH_AES_256_GCM_SHA384 in RFC5487
@mritd
Thanks. I'll provide info of how to compile and you can open a pull request.
Could we add quic support ?
Does pre-built binary have TLS1.3?
I tried use "TLS13-AES-128-GCM-SHA256" in "cipher" and it did not work.
Profile has opened TFO and BBR, After actual testing, trojan is too slow。。。
配置文件打开了TFO和BBR,然而速度慢成了翔,有没有参数提供下优化?
因为 443 端口需要提供其他服务,所以用 Nginx 做的代理。
Trojan server 启动监听 445 端口,配置 Nginx 片段:
server {
listen 443 ssl;
ssl on;
ssl_certificate /etc/letsencrypt/live/www/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
server_name 我的域名;
location / {
proxy_pass http://127.0.0.1:445;
}
}
Trojan server config:
{
"run_type": "server",
"local_addr": "0.0.0.0",
"local_port": 445,
"remote_addr": "127.0.0.1",
"remote_port": 80,
"password": [
"@777m777w"
],
"log_level": 0,
"ssl": {
"cert": "/etc/letsencrypt/live/www/fullchain.pem",
"key": "/etc/letsencrypt/live/www/privkey.pem",
"key_password": "",
"cipher": "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
"prefer_server_cipher": true,
"alpn": [
"http/1.1"
],
"reuse_session": true,
"session_ticket": false,
"session_timeout": 600,
"plain_http_response": "",
"curves": "",
"dhparam": ""
},
"tcp": {
"prefer_ipv4": false,
"no_delay": true,
"keep_alive": true,
"fast_open": false,
"fast_open_qlen": 20
},
"mysql": {
"enabled": false,
"server_addr": "127.0.0.1",
"server_port": 3306,
"database": "trojan",
"username": "trojan",
"password": ""
}
}
Trojan client config:
{
"run_type": "client",
"local_addr": "127.0.0.1",
"local_port": 1080,
"remote_addr": "我的域名",
"remote_port": 443,
"password": [
"@777m777w"
],
"append_payload": true,
"log_level": 0,
"ssl": {
"verify": true,
"verify_hostname": true,
"cert": "www/fullchain.pem",
"cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-RSA-CHACHA20-POLY1305-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384:RSA-AES128-SHA:RSA-AES256-SHA:RSA-3DES-EDE-SHA",
"sni": "",
"alpn": [
"h2",
"http/1.1"
],
"reuse_session": true,
"session_ticket": false,
"curves": ""
},
"tcp": {
"no_delay": true,
"keep_alive": true,
"fast_open": false,
"fast_open_qlen": 20
}
}
Trojan 服务器一直提示握手失败:
[2019-02-21 16:48:54] [ERROR] 183.83.69.87:1653 SSL handshake failed: wrong version number
[2019-02-21 16:48:54] [INFO] 183.83.69.87:1653 disconnected, 0 bytes received, 0 bytes sent, lasted for 0 seconds
请问我应该如何配置代理转发?
China is pursuing quantum supremacy and we should prepare for it.
IETF has an idea called Quantum-Safe Hybrid (QSH) Ciphersuite for TLS.
Here is the document:
https://tools.ietf.org/html/draft-whyte-qsh-tls13-02 (For TLS 1.3)
https://tools.ietf.org/html/draft-whyte-qsh-tls12-02 (For TLS 1.2)
WolfSSL library has implemented QSH ciphersuite.
https://www.wolfssl.com/quantum-safe-wolfssl-2/
Sorry, I was too lazy to create a PR for review.
Since the boost version basically works I was looking for some quick hacks to speed it up.
diff --git a/src/clientsession.cpp b/src/clientsession.cpp
index ff425c4..3d9d8fd 100644
--- a/src/clientsession.cpp
+++ b/src/clientsession.cpp
@@ -111,6 +111,17 @@ void ClientSession::in_recv(const string &data) {
auto self = shared_from_this();
resolver.async_resolve(query, [this, self](const boost::system::error_code error, tcp::resolver::iterator iterator) {
if (!error) {
+#if BOOST_OS_LINUX
+#ifndef TCP_FASTOPEN_CONNECT
+#define TCP_FASTOPEN_CONNECT 30
+#endif // TCP_FASTOPEN_CONNECT
+ using fastopen_connect = boost::asio::detail::socket_option::boolean<BOOST_ASIO_OS_DEF(IPPROTO_TCP), TCP_FASTOPEN_CONNECT>;
+ boost::system::error_code ec;
+ // Will throw.
+ out_socket.lowest_layer().open(iterator->endpoint().protocol());
+ // Ignores error in case the feature is not available.
+ out_socket.lowest_layer().set_option(fastopen_connect(true), ec);
+#endif // BOOST_OS_LINUX
out_socket.lowest_layer().async_connect(*iterator, [this, self](const boost::system::error_code error) {
if (!error) {
out_socket.async_handshake(stream_base::client, [this, self](const boost::system::error_code error) {
diff --git a/src/serversession.cpp b/src/serversession.cpp
index 6fa1cbc..9ebe0d7 100644
--- a/src/serversession.cpp
+++ b/src/serversession.cpp
@@ -103,6 +103,17 @@ void ServerSession::in_recv(const string &data) {
tcp::resolver::query query(req.address, to_string(req.port));
resolver.async_resolve(query, [this, self](const boost::system::error_code error, tcp::resolver::iterator iterator) {
if (!error) {
+#if BOOST_OS_LINUX
+#ifndef TCP_FASTOPEN_CONNECT
+#define TCP_FASTOPEN_CONNECT 30
+#endif // TCP_FASTOPEN_CONNECT
+ using fastopen_connect = boost::asio::detail::socket_option::boolean<BOOST_ASIO_OS_DEF(IPPROTO_TCP), TCP_FASTOPEN_CONNECT>;
+ boost::system::error_code ec;
+ // Will throw.
+ out_socket.open(iterator->endpoint().protocol());
+ // Ignores error in case the feature is not available.
+ out_socket.set_option(fastopen_connect(true), ec);
+#endif // BOOST_OS_LINUX
out_socket.async_connect(*iterator, [this, self](const boost::system::error_code error) {
if (!error) {
Log::log_with_endpoint(in_endpoint, "tunnel established");
diff --git a/src/service.cpp b/src/service.cpp
index 57001f4..10d130c 100644
--- a/src/service.cpp
+++ b/src/service.cpp
@@ -37,6 +37,12 @@ Service::Service(Config &config) :
config(config),
socket_acceptor(io_service, tcp::endpoint(address::from_string(config.local_addr), config.local_port)),
ssl_context(context::sslv23) {
+#if BOOST_OS_LINUX
+ using fastopen = boost::asio::detail::socket_option::boolean<BOOST_ASIO_OS_DEF(IPPROTO_TCP), TCP_FASTOPEN>;
+ boost::system::error_code ec;
+ // Ignores error.
+ socket_acceptor.set_option(fastopen(true), ec);
+#endif // BOOST_OS_LINUX
auto native_context = ssl_context.native_handle();
if (config.ssl.sigalgs != "") {
SSL_CONF_CTX *cctx = SSL_CONF_CTX_new();
TCP Fast Open removes 1 RTT. After this patch:
-> SYN, Client Hello
1 RTT
<- SYN/ACK
<- Server Hello, Change Cipher Spec, ...
-> Change Cipher Spec, ...
1 RTT
<- some more TLS parameters
-> GET / HTTP/1.x
1 RTT
<- HTTP/1.x OK
(This is TLS 1.3 draft 22 though. I didn't see TLS 1.2 session resumption working??)
从openssl 1.1.1开始,带了一个SSLKEYLOGFILE功能,生成的文件可以配置给wireshark用来debug,或者是蛋疼看TLS payload。可以参照 openssl/openssl@4bf73e9
Hi @GreaterFire,
I find this project is quite interesting. It may be necessary to move on to SOCKS5 over TLS in the near future.
I'm wondering if you can implement SIP003 to let your project work with shadowsocks. If so, this project would get supported on all the known platforms and devices instantly.
If you have any question, please let me know.
Thanks,
Max
Explain: English is not good, using machine translation.
PS: Not deep understanding of the network, if any errors, please correct me
PS2: QUIC using UDP may be QOS
According to some issues, here is a list of improvements to be made to the protocol only if necessary. You are welcomed to contribute to this list.
Since some strategies cannot be proven effective, further discussions are required.
hi。
server.json里的curves的值怎么填?
Packaging Status:
Status | Distribution | Maintainer | Notes |
---|---|---|---|
✖️ | Alpine | ||
✔️ | AOSC | Various | |
✔️ | Arch | @felixonmars | |
✔️ | AUR | @axionl | Tracks master branch |
✔️ | Debian | @GreaterFire | |
✖️ | Fedora | ||
✔️ | Gentoo | @YangMame | |
✖️ | openSUSE | ||
✖️ | OpenWrt | @wongsyrone | lede |
If you are interested in becoming a maintainer to maintain trojan packages for some Linux distributions, please reply to this issue.
There is a certain website resolved to one ipv4 address and one ipv6 address. The resolved ipv6 address does not work (curl -6 https://the.website
times out).
In my testing the trojan server connects to the ipv6 address and does not work. It should be able to connect to the ipv4 address.
So far it's just one case. I used this workaround.
--- a/src/serversession.cpp
+++ b/src/serversession.cpp
@@ -103,6 +103,14 @@ void ServerSession::in_recv(const string &data) {
tcp::resolver::query query(req.address, to_string(req.port));
resolver.async_resolve(query, [this, self](const boost::system::error_code error, tcp::resolver::iterator iterator) {
if (!error) {
+auto v4it = iterator;
+for (auto v4it = iterator; v4it != tcp::resolver::iterator(); ++v4it) {
+ const auto& addr = v4it->endpoint().address();
+ if (!addr.is_v6()) {
+ iterator = v4it;
+ break;
+ }
+}
out_socket.async_connect(*iterator, [this, self](const boost::system::error_code error) {
if (!error) {
Log::log_with_endpoint(in_endpoint, "tunnel established");
This is not limited to ipv4/6 dual stack resolutions. If a domain name resolves to multiple addresses and one of them doesn't work, the resolver needs to do something intelligent to blacklist that not working address.
Not action is required at this time. In the future using chromium's network stack should automatically solve this problem.
For example, https://github.com/trojan-gfw/trojan/blob/master/docs/config should be https://github.com/trojan-gfw/trojan/blob/master/docs/config.md. And so are other URLs. Regards.
I would like to invite you to the discussion of the rationales and ideas for a better circumvention protocol.
Many of the points below can have better context with citations but I try to keep it informal this time.
The Shadowsocks specification has been reinventing cryptography to make up for apparent vulnerabilities from various probing attacks. It among other similar protocols try to recommend specific cipher suites and cryptographic configurations without professional analysis and audit. The fact that the Shadowsocks spec was fixed again and again with faulty cryptographic designs shows how hard it is to reinvent cryptography and why obfuscation is not possible without certain level of security.
This subject has been much better researched and engineered for years as TLS. TLS provides confidentiality, authentication, and integrity. It protects against replay attack. It has mature and high performance and cross-platform implementations. It is only sensible to adopt commonly used best practices. Those who do not understand TLS are doomed to reinvent it, poorly.
What Shadowsocks is doing is no different from Tor's pluggable transports, e.g. ScrambleSuit and obfs4, which have designed custom cryptographic protocols to replace Tor's default TLS stack, except that Tor's protocols are scholarly peer-reviewed.
The assumption of these Tor PT protocols is that if the wire data look as random as possible (above the transport layer) it would be impossible to identify or classify. This assumption has its limitation. It is shown that random packet padding actually becomes a feature in itself and enables new entropy-based attacks.
The bigger picture is that most traffic on the Internet does not look random. If an obfuscation protocol makes the data too random it attracts additional scrutiny. A thought experiment: the GFW intercepts 60% HTTP, 30% TLS, and 10% unrecognized high-entropy traffic. After the initial coarse traffic classification, the 10% traffic gets redirected for additional analysis, where more advanced methods become affordable.
The obvious solution is to obfuscate above the transport layer inside real TLS. By moving the protocol up the layer, traffic classification at the transport layer is less effective and the obfuscated traffic is less likely to be scrutinized by being of a larger traffic class. (Note that it must be real TLS. Mimicry of HTTP (or TLS) has been shown to be easily detected.) I think this is part of the reason Meek (plain HTTPS proxy with fake TLS SNI) is given more attention at Tor. As more traffic moves to TLS this effect becomes more pronounced.
TLS is much more complex than TCP and give off much more information, mostly in TLS parameters in ClientHello and ServerHello, state transition, and certificates.
In principles these protocol behaviors can be imitated perfectly by reusing a browser's TLS stack and it is easy to verify the imitation locally.
GFW people have proposed to prioritize traffic for more advanced analysis by a "trustworthiness" ranking of the certificates. This is essentially network-layer host behavior analysis applied at the TLS layer and the certificates are the new IP addresses. Indeed IP addresses can also have "trustworthiness" used to prioritize traffic for analysis, e.g. if 99% traffic of a foreign host is with a single domestic host, select it for advanced tunnel traffic classifiers; well-known IP addresses are whitelisted, etc.
Traffic selection is always happening and it's a matter of degree of uniqueness of the certificates. In this sense CA-signed certificates (Let's Encrypt) can be even more unique than self-signed certificates because the former may represent less traffic than the latter. There are no clear wrong options here for circumvention but the choice of best practice remains an open question.
TLS handshakes introduce additional RTT on top of TCP handshakes. Latency is critical for network performance.
The Shadowsocks protocol has no handshakes and its implementation uses TCP Fast Open which reduces even more handshake RTT. Although TCP Fast Open is not always usable as it is commonly obstructed by middleboxes.
Speaking of RTT, VPNs at the network layer would have the least RTT among proxy schemes, but VPNs' usability is harmed by its requirement to configure the OS network stack. In this sense Shadowsocks' success is partly due to the fact that it requires little sysadmin work which is a reasonable tradeoff for TCP handshake RTT.
There are remedies in TLS for the RTT problem. TLS 1.2 False Start extension reduces handshakes to 1-RTT. TLS 1.3 (draft) introduces a 0-RTT mode. But TLS 1.3 implementations are still not production-ready to match the 0-RTT performance in Shadowsocks protocol (I tried Chromium/BoringSSL, Nginx. Though HAProxy just put out 0-RTT support in 1.8-rc3, I was working with Nginx because it's easier for scripting. I hope I can get them working soon.)
About TCP Fast Open, I found neither Nginx nor HAProxy has implemented it in client mode. Nginx gave an interesting reason: it's better to use persistent connections instead of creating new connections very fast. Shadowsocks creates a new proxy connection for each client request. It is arguable whether multiplexing would be better than that for Shadowsocks, but the benefit is obvious in the case of TLS where the cost of creating new connections is high.
There are two schemes of multiplexing: one is multiplexing multiple streams into a single TCP connection, the other is connection reuse/connection pooling. Mux.Cool used by V2Ray is of the first scheme. The first scheme has a head-of-line blocking problem which increases latency, see this. The second one is used by Nginx as "keepalives." It works like this: For a new client connection, try to use an idle proxy connection in the pool or create a new connection; after the client connection is closed, do not close the proxy connection instead save it into the pool as idle (with an idle timeout).
The Shadowsocks protocol does not allow multiplexing because it cannot distinguish the start and end of streams. Neither does the Trojan protocol but Trojan can be extended to allow this enhancement. To enable multiplexing the protocol can use a similar scheme as HTTP chunked transfer encoding:
I agree this is a legitimate threat and deserves attention. There has been a report of a specific TLS-in-TLS proxy being repeatably detected by traffic analysis, but at the same time GFW people have also admitted the limitation of practical traffic analysis (classifiers do not generalize, concept drift, etc.).
The difficulty at the circumvention side is that there is no way to verify the effectiveness of any proposed traffic obfuscation technique in real-world setting and similarly there is no way to compare their relative effectiveness.
Despite the theoretical trouble I think the current recommendation is to implement any basic packet padding scheme, which will be always better than no padding. More adversarial implementations of detectors of traffic obfuscators may prove useful in measuring the strength of them.
@GreaterFire @micooz @WANG-lp @bosskwei @wongsyrone
git clone https://github.com/trojan-gfw/trojan
cd trojan/
git checkout stable
mkdir build
cd build/
cmake ..
after running "cmake .." ,i encounter error as follows:
...
CMake Error at /usr/local/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
system variable OPENSSL_ROOT_DIR: Found unsuitable version "1.0.1t", but
required is at least "1.0.2" (found /usr/lib/x86_64-linux-gnu/libcrypto.so)
Call Stack (most recent call first):
/usr/local/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:376 (_FPHSA_FAILURE_MESSAGE)
/usr/local/share/cmake-3.10/Modules/FindOpenSSL.cmake:379 (find_package_handle_standard_args)
CMakeLists.txt:12 (find_package)
-- Configuring incomplete, errors occurred!
See also "/root/trojan/build/CMakeFiles/CMakeOutput.log".
See also "/root/trojan/build/CMakeFiles/CMakeError.log".
root@yms:~/trojan/build#
i already uprade openssl to version1.0.2:
root@yms:# which openssl# openssl version
/usr/local/ssl/bin/openssl
root@yms:
OpenSSL 1.0.2n 7 Dec 2017
how to fix it?
thank you
The trojan build instructions should be clear and on the git project page
Combing through the readme.md and multiple other folders doesn't even add any further how-to on this. Attempting cmake, ./configure results in zip, nada. Fill in the current missing build instruction blanks in the git project page and add the build-compile instructions in a tiny .txt file for the main directory folder.
Since when run in server mode, we usually deploy a web server as well. Can we add uds for even better performance?
My client is Windows 10 and Trojan works perfect. There is only one issue. I enabled fastopen (include trojan config and system operation) on bothside but I got this.
Welcome to trojan 1.10.0
[2019-01-26 11:20:22] [WARN] TCP_FASTOPEN_CONNECT is not supported
[2019-01-26 11:20:22] [FATAL] trojan service (client) started at 127.0.0.1:800
I don't know why, here is my config.
# server config
"tcp": {
"prefer_ipv4": true,
"no_delay": true,
"keep_alive": true,
"fast_open": true,
"fast_open_qlen": 20
}
# client config
"tcp": {
"no_delay": true,
"keep_alive": true,
"fast_open": true,
"fast_open_qlen": 20
}
Is there any plan to release a Android client?
the above error always popups after starting projan server. anyone can help?
Please add custom DNS support to config file.
Instead using DNS provided by OS, this will allow user to config custom DNS server in trojan.
I've edited the "config.json" file and downloaded the "private.crt" to the directory
"cert": "/etc/ssl/cert.pem"
"cert": "private.crt"
,
which one is correct?
When i run the trojan exec file,it shows :
[2019-02-22 09:44:54] [FATAL] fatal: config.json: cannot open file
[2019-02-22 09:44:54] [FATAL] exiting. . .
what's wrong? please help.
trojan: error while loading shared libraries: libboost_atomic.so.1.65.1: cannot open shared object file: No such file or directory
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.