Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP routage broken by REDIRECT to a single port for ss-redir #1078

Open
thepaka opened this issue Sep 19, 2019 · 1 comment
Open

TCP routage broken by REDIRECT to a single port for ss-redir #1078

thepaka opened this issue Sep 19, 2019 · 1 comment

Comments

@thepaka
Copy link

thepaka commented Sep 19, 2019

I am using the OverTheBox solution for a few months and I found an issue with TCP connections that manifests itself in an abnormal number of timeouts.

After some research, it turns out that the problem is quite simple.

Parallel connections from a same source address and source port to different destinations cannot be established because of the REDIRECT NAT rules used for ss-redir. When using a single port for the REDIRECT, those parallel connections cannot be differentiated anymore (same source & destination).

I'm testing a patch on the "OverTheBox Plus" hardware, which makes the 4 ss-redir instances to listen on 2 ports (2 instances per port, seems that using only one instance per port has a negative performance impact). Something similar should also be done for the TOS/DSCP ports.

--- /etc/init.d/shadowsocks.orig	2019-09-18 16:37:28.612134109 +0200
+++ /etc/init.d/shadowsocks	2019-09-18 16:49:48.062372463 +0200
@@ -135,11 +135,7 @@ _shadow_init_once() {
 	_launch_tracker "$1"
 }
 
-# This function launches one shadowsocks per CPU
-# $1 is a ref to the shadowsocks uci section (type =client)
-_launch_shadow() {
-	local cpu_count
-
+_get_cpu_count() {
 	# Determine the number of CPU cores
 	if [ -f /proc/cpuinfo ] && command -v awk &> /dev/null; then
 		# This is a hacky way to get the number of cores (we don't want the
@@ -156,10 +152,18 @@ _launch_shadow() {
 		_log 3 "Couldn't determine CPU number because of missing /proc/cpuinfo or awk. Falling back to 1 CPU."
 		cpu_count=1
 	fi
+}
+
+# This function launches one shadowsocks per CPU
+# $1 is a ref to the shadowsocks uci section (type =client)
+_launch_shadow() {
+	local cpu_count lport
+	_get_cpu_count
+	config_get lport "$1" lport
 
 	for i in $(seq 1 $cpu_count); do
 		procd_open_instance
-		procd_set_param command "$PROG" -c "$PROG_CONF" -b 0.0.0.0
+		procd_set_param command "$PROG" -c "$PROG_CONF" -b 0.0.0.0 -l $(( lport - i % ( cpu_count / 2 ) ))
 		procd_set_param file "$PROG_CONF"
 		procd_set_param limits nofile="51200 51200"
 		procd_set_param respawn 0 10 0
@@ -199,7 +203,8 @@ _update_conf_and_ipt() {
 
 # $1 is a ref to the shadowsocks uci section (type =client)
 _populate_ipt_socks_redir() {
-	local lport
+	local cpu_count lport
+	_get_cpu_count
 	config_get lport "$1" lport
 
 	# First, reset the chain
@@ -211,7 +216,7 @@ _populate_ipt_socks_redir() {
 			-m comment --comment "CS$i"
 	done
 	# Let's add the default rule at the bottom
-	$IPT -A socks_redir -p tcp -j REDIRECT --to-ports "$lport"
+	$IPT -A socks_redir -p tcp -j REDIRECT --to-ports "$(( lport - cpu_count / 2 + 1 ))-$lport"
 }
 
 # To update the ipset "socks_bypass", we actually
@angt
Copy link
Contributor

angt commented Sep 19, 2019

Excellent! Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants