How to realize pipeline mode (long live connection) - Trojan-Plus-Group/trojan-plus GitHub Wiki

Abstract

  • Why the simple poxy way of trojan is suppose to have high latency?
  • How to resolve it? (Classes after adding this new mode)
  • Q&A

Why the simple poxy way of trojan should have high latency?

I use a image to explain why (Google draw image): Google draw image

I don't want to explain more, the flow is very clear, if you don't understand, please reivew TCP and TLS handshake protocal.

How to resolve it? (Classes after adding this new mode)

So the simplest idea is creating a long live TCP connection(pipelines) for all connections to get rid of establishing TCP TLS handshake for every single query.

Google Draw Image

The following image is classes design graph:

Obviously we can see two classes create and mantain a long live connections between trojan client and server. Now we take a Q&A to explain some detail tech problem.

Q&A

Q: How many pipelines should be created in a begin of proxy client startup? Just one?

A: Of course not, you can set it in trojan config:

{
    "run_type": "client",
    "local_addr": "0.0.0.0",
    "local_port": 2062,
    ...
    "experimental":{
        "pipeline_num" : 5,
        "pipeline_ack_window" : 10
    }
}

Q: How to distinguish different session and trojan client?

A: I create a session id (uint16_t), starts from 0, when it's greater than max of uint16_t, it will start from 0 again. Every query from client session would allocate a unique id, and the id is increased by itself. So here's a key, if a number of connections your proxy trojan client keeps is greater than 64K at same time, trojan system would be crashed. You can review the constructor of Session.


Q: How to avoid that high bandwidth client floods remote-ends with low bandwidth? Does it decrease bandwidth?

A: As I designed, header of pipeline request (protocol) has a 3-7 bytes length, and each data of TCP must send a extra ACK message to limit flooding problem.

/*
|-------------------|-----------------------|---------------------|-----------------------|
| 1 byte as command | 2 bytes as session id | <2 bytes as length> | <trojan request data> |
|-------------------|-----------------------|---------------------|-----------------------|
*/

You can review code PipelineRequest class for the detail, this protocol is above trojan original protocol.

And before sending data, query client must be wait for ACK message from trojan server, otherwise, trojan client has to cache many of message and increase usage of system memory, up to 100MB when I test via speedtest.net.

Of course, every single message will attach more 3-7 bytes header, might slow down your bandwidth a tiny tiny bit.


Q: How to test this mode?

A: I test new code via following ways:

  • speedtest.net, starting a trojan with "client" type and server in one desktop machine, just for bandwidth test, loadtest. This test will cover TCP mode.
  • starting a trojan with "client" type in a desktop machine, with a Android BifrostV app, to test UDP+TCP mode, of course, many Google app with UDP protocal have been installed in my phone.
  • starting a trojan client with "forward" type and server in same desktop machine, with nc(ncat in windows) to test UDP + TCP forward.
  • starting a trojan client with "nat" type in my linux system as a software-router, might be known as "transparent proxy", and a real server outside of GFW, this way I test every day, ha~