trojan-gfw / trojan

An unidentifiable mechanism that helps you bypass GFW.
https://trojan-gfw.github.io/trojan/
GNU General Public License v3.0
18.93k stars 3.04k forks source link

[BUG] Dns failure (wrong config) of openwrt trojan nat client results in memory leak, should that be handled gracefully? #403

Closed sgon00 closed 4 years ago

sgon00 commented 4 years ago

Trojan Version trojan 1.15.1 at openwrt

Note: the wrong config itself is not what I concern. I have already fixed the wrong config.

The Story

This problem actually happens because I didn't configure dns lookup and iptables rules properly.

My wrong config: The trojan is running at "nat" run_type and the remote_addr has a host domain value instead of IP, and local_port is 12345. The dns server of the router is set to 8.8.8.8 with tcp request only. I forward 8.8.8.8 tcp traffics to local port 12345.

In the end, you can see that trojan client won't be able to resolve the remote_addr host domain to ip address. (Btw, my laptop was connected to this trojan router, so there were also some background http/https requests to trojan from apps such as chrome with opened tabs etc.)

The actual error msg from logread daemon.err trojan[11240]: [ERROR] 192.168.1.148:54352 cannot resolve remote server hostname myhostserver.com: Host not found (non-authoritative), try again later

I have corrected this mis-config by putting ip-host values at /etc/hosts. This is not what I concern. The thing is this kinda wrong config results in eating all 256MB of my router ram (memory leak), trojan ends up with [FATAL] fatal: std::bad_alloc and my router was kinda frozen too.

I think trojan should be able to handle this failure more gracefully instead of memory leak and froze the entire system.

Thanks a lot for your time.

Chigusa0w0 commented 4 years ago

Personally I don't think it must be fixed as you have created an infinite loop which is not expected. Also, you may use both remote_addr (set to IP) and sni (set to SNI a.k.a. "domain") fields in configure file to get around the situation of potential DNS pollution without touching HOSTS file.

As Trojan currently do not read data transmitted in your connection, Trojan has no way to know where you send your DNS requests to. It would be very hard and inaccurate to determine whether an infinite loop has occurred. So, Trojan must either do some nasty staff on your data or merely guess what is happening to provide the requested function.

But for final decision, please respect @GreaterFire 's opinion.

GreaterFire commented 4 years ago

@sgon00 Sounds more like a resource exhaustion due to infinite recursion than a "resource leak". Can you provide valgrind log under incorrect configuration just to make sure it's not leaking?

sgon00 commented 4 years ago

Thank you both very much for the replies.

Regarding sni field, I knew I could provide IP to remote_addr and domain to sni. But due to the limited of my knowledge, I am afraid if GFW can examine traffic packets differences between IP remote_addr and domain remote_addr. (Thus if any differences between IP remote_addr config https request/resposne AND a normal browser https request/response). That's why I keep remote_addr using a domain name and put the ip-host resolv in /etc/hosts. If dev can confirm there is no difference at all between an IP remote_addr and domain remoteaddr. I will safely swtich to that config. ^^

@GreaterFire Thank you very much for the reply. My current testing router only has 4MB flash and no space left on /overlay to install valgrind. (btw I never use valgrind before). If you have to look at the valgrind log in order to fix/examine it, I will have to configure another more powerful router for tihs purpose. Please let me know if valgrind log is must to have. Thanks.

Chigusa0w0 commented 4 years ago

The difference is that a domain remote_addr will request DNS resolve (then use the resolved IP to establish connections) while an IP remote_addr will not. But since you have fully encrypted your DNS requests and use HOSTS to avoid loop, there will be no difference for third-party adversaries.

sgon00 commented 4 years ago

@LimiQS thank you very much for the detail explanation. 😀

GreaterFire commented 4 years ago

@sgon00 Putting IP (hostname in sni) or hostname in the remote_addr field are completely equivalent.