shadowsocks / shadowsocks-rust

A Rust port of shadowsocks
https://shadowsocks.org/
MIT License
8.67k stars 1.18k forks source link

Running on router: memory allocation of 327660 bytes failed #1679

Open ameir opened 1 month ago

ameir commented 1 month ago

I am trying to run this on a router, and while it works, it only works for a very short period of time. Shortly after I set it as the default route, I get the following message before it aborts: memory allocation of 327660 bytes failed.

This is a Linksys EA6900 router with 255MB of memory. Do you have any thoughts/suggestions on how I can overcome this issue? I am also currently bypassing Shadowsocks for my DNS resolvers to avoid overwhelming it with UDP requests.

For reference, this is how I am invoking it:

sslocal --server-addr "xxxx" \
    --password "xxxx" \
    --encrypt-method "chacha20-ietf-poly1305" \
    --protocol tun --local-addr="127.0.0.1:8444" -U  \
    --tun-interface-address "192.168.220.1/24"
zonyitoo commented 1 month ago
memory allocation of 327660 bytes failed.

327660 is 319KB. So your system couldn't even allocate 300KB more memory.

You could check with any tools, like top or ps, to monitor how many sslocal was using after start, and before it crashes. If it actually requires memory that is far more than your system could provide, you should try:

  1. Use redir instead of tun. tun runs a user space network stack in the process, which actually requires many memory.
  2. Compile sslocal yourself by disabling any components that you don't actually need.
ameir commented 1 month ago

I ran top -d 1 while using it, and saw that the memory usage was ballooning (all with a single process). This was using a binary I built locally with ./build-release -t armv7-unknown-linux-musleabi -f local-tun. Do you think it's worth trying a jemalloc build?

I'm currently using https://github.com/go-gost/gost/ with a tun interface with good results (e.g. no memory issues), but it is much slower than shadowsocks overall.

zonyitoo commented 1 month ago

Do you think it's worth trying a jemalloc build?

Well, I don't think it would help, theoretically. Jemalloc is superior to libc's default memory allocator only when threads >12, which normally wouldn't happen in resource limited system, like routers.

You may also try to lower 20 to 10 to minimize memory consumption for every TCP tunnel:

https://github.com/shadowsocks/shadowsocks-rust/blob/15ed4a890d935229def66e6fbc96e91e9b1baf7a/crates/shadowsocks-service/src/local/tun/tcp.rs#L46-L47

ameir commented 1 month ago

Thanks for the tip. The tunnel lasts much longer with that adjustment, but I ultimately end up with memory allocation of 163830 bytes failed while trying to do a speedtest. Basic browsing seems to work, unlike before this adjustment, where it would OOM much earlier.

zonyitoo commented 1 month ago

For speedtests, packets may be piled up in these two channels:

https://github.com/shadowsocks/shadowsocks-rust/blob/c76f8b261c574849a1ce8bdf4c76a8e4f1efa6bf/crates/shadowsocks-service/src/local/tun/virt_device.rs#L34-L35

You may try to modify it to a bounded channel to limit the total pending packets in memory.