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

Some extra ways of active probing #2539

Closed
nametoolong opened this issue Jun 3, 2020 · 6 comments
Closed

Some extra ways of active probing #2539

nametoolong opened this issue Jun 3, 2020 · 6 comments

Comments

@nametoolong
Copy link

nametoolong commented Jun 3, 2020

There are a couple of possible ways of active probing, even with #2523 patched. Most of them are probabilistic and not easy to exploit, and I am only posting two obvious attack vectors here. V2Ray's VMess implementation seems to be pretty broken by now.

-----BEGIN PGP MESSAGE-----

hQIMA/yg09s4zMcsARAAwcrAYlEIYbZlP/m/V73NZ4ODcLQOhCTJ7HAwgVlOAGhi
Cd9YGl6Z9DaW5qUtomvmZsxagGrgIHIIa3jXb6Z1d9ycIAbdque4qwmhA1MjvvaI
KQt7H4CTByr6NF2YZVYIJp8oICQeEUWrZxhS5JPN4kORBpJQfYJ8FfPrzRvtXOBa
RiOudQO3+iesMDPR09cHRfrC3aH/TD578Un4zjdBguJBVb6yO8yQ18P7ZvyeFb2r
/tPK6coP7J6gos+fg59gvL2XjDmCoPxpyN8d2BjBxJfR9XjVhNWCQ5xVkVWUXrv5
IHGFJBn3nebS3yWBp3QILviIw0ZreJpB9l+kBgjKBSlhFwOd7h0aHShHdP+pmi9Y
HHMzUzRpDHhoP9sw9WqSVxiRoflqh782yYo+BfVyWn1iGOpoHh6EO2Ozu3FIJBcQ
OZGZ3ZiLC18DXOB76gWuItkLZG9RW7+FXI4vIifCeqGoTyRkDrWjR7F6nKx3vZOL
uZwWwgjeEmZDQ6XAX/3pKB+AQBMS475xiQjJCIK9+ehDKhz/R9GHw1e6ebLLK+M1
EHZT50H4Unuyg3F8v8lmtc+pkvzWc0TIz5cesUN9IUb8CVtKZrWCK0Ydpm4uG9J/
xHfZt1V9k//jUOet65qZGRQvHeg+dklXIV7fIZpezeerG4zs9TIgVxxGjFX6bEDS
6QGI7k6PKUyT+l278KoZ5voco2qsyQ9jAQ+K/u6OKBMuhPbjuZYVa4mMf3IedEDu
eJM+xjdGev7iMQY1jybGKJo9Op5huKSI0fVXtMuvIJZNtVqJEQxt8lrcNNcvCdS1
J2QsBgyHtnFiP4IlurkW1ZlphxgAQpLkTdQsf/rRTo/V8bFpHLzg52PzXAaWuTM8
e2t+aNsP3IBII0x+NBuwpY8xRwrzLbkEEQqb0M5CBF/YK42IoXmtRXyKJze8EF/H
zk3bAtpRBvdVQNoN7eZ3rIfudTFn+4H4VJ3GZkpiZMgl59mhDAffxsPQmhiXfYGY
1QSwvn8K1ga8pIM4iQG4Qfx5+SaeSJV9LbirtAeEkc8kAyO0/CYOOqWdBj76xBEX
aaJlweZUxyeFjwChnSjw6BjEt48HkAFlYhpHhTgfhtH2Uw39KtJO+ah8Ju82P4NE
AGiE5hjx+xK7jc0wJRzBj5ZlJxFnKzTqrgN4f54QYHtKJql/j82gEaVgg+q+z9Tt
dHPkA5C+kLajFYvHJEiH+zk7i1QjBpfT9N58LjpwDzmN0zgBgLBLGBh4xutyHR95
nicpPh0WaTgFCBa96nER6fJ1GEAtKhis7INlP8hJm+rfkgsnRgz4Jd8YkmqTQVr6
9RdagO/wEWLpV/BsrAQx+EAH5UGRP+fDU2L0PhwdUjFgTPYfelLNOXIui/469uyT
A6CLzWrScKl3CUeK6cOMkpDd30Cwn0NwPrPz6nZokuNrV9r7ddKhtxIBcqnFF8Qi
UCZC4HBpJKMuSZ3MkKg=
=PC3U
-----END PGP MESSAGE-----
@xiaokangwang
Copy link
Contributor

xiaokangwang commented Jun 3, 2020

Thanks for your report, a fix to these issues have been authored but yet to be released.

The attacks described in this issue will be neutralized in the next release.

@nametoolong
Copy link
Author

nametoolong commented Jun 3, 2020

@xiaokangwang I guess there is some misunderstanding of the second attack. The second attack is even easier: now the attacker does not have to perform the attack within 30 seconds because he can trigger the drain behavior at any time.

As soon as the behavior seed is determined, BaseDrainSize and RandDrainMax is fixed and can be trivially probed across multiple connections. It takes significantly longer time but is reliable. Then we can fingerprint a server who repeatedly exposes the same drain pattern.

It seems like a dilemma: a large BaseDrainSize makes it easy to identify individual servers, while a small one provides less protection against #2523.

@xiaokangwang
Copy link
Contributor

BaseDrainSize and RandDrainMax is the characteristic of that individual server's port. And any typical TCP server will always read a certain amount of data before closing the connection. Can you describe how to determine whether a TCP server is a VMess server based on BaseDrainSize and RandDrainMax ?

@nametoolong
Copy link
Author

There are a few heuristics, but none are 'precise' enough. I think it is fine as declared in the announcement. Such uniform random behavior is actually rare but there is no protocol that is completely unidentifiable. So my apologies and thank you for your earnest work.

@xiaokangwang
Copy link
Contributor

Thanks for your contribution. The distribution of drain can always be adjusted later. You don't need to say sorry, and you deserve my homage.

@xiaokangwang
Copy link
Contributor

This issue have been resolved and the original report is declassified. Decrypted report appended below:

-----END PGP MESSAGE-----gpg: encrypted with 4096-bit RSA key, ID FCA0D3DB38CCC72C, created 2020-06-02
      "V2Fly Developers <dev@v2fly.org>"
Vector 1:
Let M1 be the first 54 bytes of a valid session.
Let M2=M1. Tamper with M2[48] (i.e. alter the 49th byte of M2).
Replay M1. Connection is closed immediately.
Replay M2. Conection is not closed.
Replay M2 again. Connection is closed immediately.

Solution:
Drain the connection on all types of errors. It still needs to be considered whether draining the connection itself is a attack vector.

Vector 2:
Let M be the first 54 bytes of a valid session.
Let M[48]=0..255.
Replay all 256 different versions of M within 30 seconds. It is not very easy to perform, but still feasible.
Check how many bytes the server swallows after sending M. Here we call the number P.
If max(P)-min(P) is very close to 48 but never exceeds 48, then it is likely a v2ray server. By testing multiple times we can gain a high confidence.

Solution:
Randomize the number to drain with other sources of seed. How to do so without breaking the deterministic random protection remains to be investigated.

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

2 participants