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

Modify packet by nftables raw payload expression, without a listening program #82

Open
Oniicyan opened this issue Feb 16, 2025 · 1 comment

Comments

@Oniicyan
Copy link

Oniicyan commented Feb 16, 2025

I have a simple scenario that I need to modify port=12345 in the HTTP request to port=54321.
The nftables rules like this work properly on non-encrypted HTTP packets:

chain BTTR_HTTP {
	@ih,768,80 0x706f72743d3132333435 @ih,800,48 set 0x3d3534333231 update @BTTR_HTTP { ip daddr . tcp dport } counter
}

I've been bothering how to modify HTTPS encrypted packets until I encounter SSLProxy.
I have basic scripting skills and network knowledge, but I don't have the ability to write a listening program. Therefore, I intend to use nftables to emulate the work of the listening program.

The nftables rules like this:

chain encrypted {
	type nat hook output priority dstnat; policy accept;
	skuid != 58443 tcp dport 443 counter redirect to 58443
 }
chain decrypted {
	type filter hook prerouting priority filter; policy accept;
	ip daddr 127.0.0.1 tcp dport 50080 @ih,0,32 0x47455420 counter tcp sport set 50080 tcp dport set tcp sport
}
chain BTTR {
	type filter hook postrouting priority filter; policy accept;
	@ih,0,112 0x474554202f616e6e6f756e63653f add @BTTR_HTTP { ip daddr . tcp dport } goto BTTR_HTTP
}

Then run sslproxy -d -u sslproxy -k ca.key -c ca.crt https 0.0.0.0 58443 up:50080.

In fact, this attempt was almost successful. I returned the packets without a real listening program, nftables recognized the decrypted HTTP data and modified it.
The problem now is that with netfilter, I can only return the packet to the source port of the current connection, not the dynamically assigned port specified in the SSLproxy line.

Image

I'll look into whether it's possible to use socat or other existing programs to identify the SSLproxy line and send back packets correctly.


Here are the feature requests.

Can other methods be used to determine the port that receives the modified packet? For example, the source/destination port of the current connection +1, or a fixed port specified at startup.

It can even be added to have a "reflection" feature that allows SSLproxy itself to act as a listening program and respond correctly so that netfilter and other framework can manage the decrypted HTTP data.

This can make SSLproxy more friendly!

@Oniicyan Oniicyan changed the title Modify packet via nftables raw payload expression Modify packet with nftables raw payload expression Feb 16, 2025
@Oniicyan Oniicyan changed the title Modify packet with nftables raw payload expression Modify packet by nftables raw payload expression, without a listening program Feb 16, 2025
@Oniicyan
Copy link
Author

Oniicyan commented Feb 23, 2025

This works:
sslproxy -d -k CA.key -c CA.crt ssl 0.0.0.0 58443 up:50080
socat TCP-LISTEN:50080,fork EXEC:socat.sh &

The socat.sh is:

#!/bin/bash
read LINE
PORT=$(echo $LINE | awk -F ':|,' '{print$3}')
exec socat - TCP:127.0.0.1:$PORT

It only works for the ssl proxyspec, where the SSLproxy line will appear on the first line of inner layer (before the HTTP request).


I improved the socat.sh. The port in the SSLproxy line can now be accurately identified and the full HTTP request is sent back after stripping.
This script works on the https proxysepc, too.

#!/bin/bash
while read -r LINE; do
	CONTENT="$CONTENT"$'\n'$LINE
	[[ $LINE == $'\r' ]] && {
		CONTENT_LENGTH=$(echo "$CONTENT" | grep -i 'Content-Length' | awk '{print $2}' | tr -d '\r')
		[ $CONTENT_LENGTH ] && {
			read -r -d '' -n $CONTENT_LENGTH BODY
			CONTENT="$CONTENT"$'\n'"$BODY"
		}
		break
	}
done
PORT=$(echo "$CONTENT" | grep SSLproxy | awk -F ':|,' '{print$3}')
CONTENT=$(echo "$CONTENT" | sed -e '1{/^$/d}' -e '/SSLproxy/d')
exec socat -,ignoreeof TCP:127.0.0.1:$PORT <<<$CONTENT

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

No branches or pull requests

1 participant