-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Description
Please describe the new feature you want in detail.
The current implementation of mKCP does VERY BADLY in hiding protocol fingerprint. Its obfuscation is solely based on the first four bytes (authentication tag) of a packet, which can easily be identified. Therefore, I propose the following changes to the mKCP transport.
- Add a new field
key
toKcpObject
. Its value should be a valid UUID. Therefore, if aKcpObject
has a non-emptykey
property, we can assume it enables keyed obfuscation as described in this issue.
{
"mtu": 1350,
"tti": 20,
"uplinkCapacity": 5,
"downlinkCapacity": 20,
"congestion": false,
"readBufferSize": 1,
"writeBufferSize": 1,
"header": {
"type": "none"
},
"key": "27848739-7e62-4138-9fd3-098a63964b6b"
}
- Use some PRNG to generate key streams for packet obfuscation.
For cryptographic soundness, we should use a KDF combined with a stream cipher to implement obfuscation. This could also fix #2131.
For superior speed, XORing the obfuscation key with the packet authentication tag, and then feed it into a plain LFSR should suffice. It runs at less than 3 cpb on modern CPUs, so it should not pose any extra performance issue.
EDIT: XORing the obfuscation key with the packet authentication tag will not work well with plain LFSRs. An extra hash invocation per packet is necessary to generate the LFSR internal state.
The bottom line is we should rely on both the 4-byte authentication tag and the obfuscation key for key stream generation, so that simply XORing two packets will not reveal a pattern.
- Add extra padding to small packets.
Currently all ACK segments have a length of an odd number (the documentation is outdated: Len
of an ACK segment is actually 1 byte long), and for heartbeat segments it is a fixed 16 bytes. I believe it should work well to append a few bytes of LFSR output to the end of a packet.