|
TechnicalFolks
Obfuscated TCP for technical folks
Obfuscated TCP uses these cryptographic primitives:
A obfuscated web server encodes a curve25519 key and a port number in a base32 encoded string called an "advert". The hostname for the webserver is a CNAME to a DNS name with the advert encoded in it. (There are issues with this, see Other advert vectors, below.) Once a client has the advert it connects to the alternative port and sends its public key. Both sides then perform key agreement and start encrypting + signing frames of data. Why not carry some of this stuff in the TCP handshake? See the project History Why not use a special HTTP escape? Because "transparent" proxies would break when clients differ from the HTTP protocol Other advert vectorsThe CNAME trick only works for names like www.example.com. If you don't have the www then you can't set a CNAME for example.com (because once you have a CNAME for a name you can only have an RRSIG record for the same name). Because of this, and for deployment reasons, we need other advert vectors. One such vector may be to put the advert in TXT records, however that requires a special DNS resolver. Also, one can put the advert in a header from the server. This means that the first time that a browser visits a given site the connection will be unencrypted because it won't know the advert. Afterwards, however, it will have it stored and can make an obfuscated connection. The first connection problem and the issue of expiring the cached adverts are cons for this solution. |
Sign in to add a comment
Why do you yse an unproven stream cipher for confidentiality, without any integrity wrapper? This is just broken in 10 different ways.
Salsa20/8 is very cheap, and an ESTREAM finalist. It is only a few years old, but it's very unlikely that future attacks on it will have work factors less than than 2^128 (AES level security). There is integrity (Poly1305, which is provably as secure as the cipher used to encrypt the nonce), but I only have 8 fingers to type with and haven't done it yet. It doesn't involve breaking the wire protocol at this point.
What caused the in-kernel version to be so large? That approach seems much more appealing to me than an HTTP+DNS-specific hack (which is still massively better than what we have anyway :).
@meepmeepmeepenator. The in kernel version was nice from a design point of view, although it has cross-platform issues of course.
Basically, it needed a whole EC Diffie Hellman implementation (which is relatively self contained) but encrypting the payloads was problematic because of the number of corner cases (consider that we have to deal with turning sendpage() into a non-zero copy operation). Also, the DH public value didn't fit within the TCP options space, and thus it needed to change the TCP state machine to transmit the value from the client in case of packet loss. It all added up.
Plus, the IETF would have kittens if I suggested the idea ;)
I /hope/ you guys are going to kick some ass at the plenary in Minneapolis, if you really think the IETF is such a huge roadblock.
So one of the nice things about SSL & Kerb5 is multiple cipher support. Eventually AES will be superseded, but SSL will let us roll out the successor gradually, in an (optionally) backward-compatible way. Does obstcp have any provisions for future ciphers, without breaking it on the wire?
Yes, the CNAME is a magic string ("ae0xx") followed by a base-32 encoded advertisement. The advertisement format is extensible, and flags to indicate support for new cipher suites can be added in the future.
Also, clients look for the advertisement anywhere in the DNS name. Future specs could add entirely new magic string prefixes with clients taking the first one they support.
If you use anything else than TCP ports 80 and 443 it will not be accessible from many places.
@banguerski: that's sadly true. Browsers will have to detect when outbound ports are blocked and fall back so as not to break anything for such users.
However, using port 80 would break anyone behind a transproxy. Using 443 is possible, and up to the webmaster, however that would generally preclude using HTTPS for the same site.
Why couldn't obsTCP share port 443 with normal SSL/TLS? The initial bytes of incoming SSL/TLS are well defined; as long as obsTCP sends something else/has a fixed first few bytes, the server should be able to detect what the client is trying to use (assuming a client-talks-first approach in obsTCP). At that point, you might be able to implement obsTCP as a patch to OpenSSL and not the webserver itself...making it support more webservers without having to explicitly patch them.
Can you check for a transproxy in the first connection and use/not use obstcp accordingly? Some connections are transproxy on port 80 only so it could be worth checking another port as well.
@KittenExploring?: You're correct that transproxies fail when using non-HTTP protocols over port 80: ObsTCP switches to another port to avoid transproxies. However, that presents problems in itself with overly restrictive firewalls and may be a reason to use the TLS transport (port 443, usually unrestricted) or to run ObsTCP over port 443. Browsers, I expect, will need to detect such ill-behaving networks and back off but the code doesn't yet.
Cheers