v2fly / v2ray-core

A platform for building proxies to bypass network restrictions.
https://v2fly.org
MIT License
29.48k stars 4.66k forks source link

utls and Nginx problem #2488

Closed Mahyar24 closed 1 year ago

Mahyar24 commented 1 year ago

Which version of V2Ray are you using? V5.4.1

If the server and client are using different versions, please indicate. Nope.

What is your use case? To bypass censorship in Iran, clients can connect to a middle VPS located within Iran, which will then connect to a VPS V2Ray located in the Netherlands.

What is the abnormal phenomenon you see?

  1. I am using a WebSocket outbound on my Iran VPS (client here) to connect to my Netherlands Nginx and eventually V2Ray (without CDN). When I use it with tls as security, everything works fine, but when I use 'utls', nothing works. So, I investigated and found out that Nginx will complain that client sent plain HTTP request to HTTPS port while reading client request headers (Nginx is set up on 443 SSL). Even if I change the security parameter to something gibberish (e.g., "security": "WTF"), it has the same effect, and V2Ray will not complain or crash! So, I am worried that even if I discard Nginx and connect two V2Ray directly ("security": "utls" works fine without Nginx between them but I'm not sure if there is any encryption), packets will be transferred without any tls encryption.
  2. I supposed utls would change the User-agent too, but even with utls, the User-agent is always Go-http-client/1.1, which is easy to exploit and banned.

What normal behavior do you expect to see?

  1. If something gibberish is within the config file, V2Ray will crash or complain (at least on debug log level).
  2. utls can work with Nginx.
  3. There will be a way to change User-agent to something common (e.g. Firefox).

V2Ray client outbound:

{
  "protocol": "trojan",
  "settings": {
    "servers": [
      {
        "address": "x.xxx.com",
        "method": "aes-256-gcm",
        "password": "some password",
        "port": 443
      }
    ]
  },
  "streamSettings": {
    "network": "ws",
    "security": "utls",
    "securitySettings": {
          "imitate": "randomized",
          "tlsConfig": {
            "alpn": [
              "http/1.1"
          ],
          "minVersion": "1.3",
          "serverName": "x.xxx.com"
      },
    },
    "wsSettings": {
      "headers": {
        "Host": "x.xxx.com"
      },
      "path": "/trw/",
    }
  },
  "tag": "trojan_ws_utls"
}

V2Ray server Inbound:

{
  "tag": "trojan_ws",
  "port": 3333,
  "protocol": "trojan",
  "listen": "127.0.0.1",
  "settings": {
    "clients": [
      {
        "password": "some password",
        "email": "user@x.com"
      }
    ]
  },
  "streamSettings": {
    "network": "ws",
    "wsSettings": {
      "path": "/trw/"
    }
  }
}

Nginx setup:

server {

        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name x.xxx.com;

        error_log   /var/log/nginx/x-xxx-com.error.log;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/x.xxx.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/x.xxx.com/privkey.pem;

        location /trw {
                if ($http_upgrade != "websocket") {
                     return 404;
                }
                if ($ir_ip != 1) {
                     return 403;
                }
                proxy_redirect off;
                proxy_pass http://127.0.0.1:3333;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Nginx log:

2023/05/01 21:17:26 [debug] 1178497#1178497: *21 write new buf t:1 f:0 000056554F3B9D88, pos 000056554F3B9D88, size: 145 file: 0, size: 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http write filter: l:0 f:0 s:145
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http output filter "/trw/?"
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http copy filter: "/trw/?"
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 image filter
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 xslt filter body
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http postpone filter "/trw/?" 000056554F3B9EE0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 write old buf t:1 f:0 000056554F3B9D88, pos 000056554F3B9D88, size: 145 file: 0, size: 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 write new buf t:0 f:0 0000000000000000, pos 000056554DB11BC0, size: 202 file: 0, size: 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 write new buf t:0 f:0 0000000000000000, pos 000056554DB12C00, size: 46 file: 0, size: 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http write filter: l:1 f:0 s:393
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http write filter limit 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 writev: 393 of 393
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http write filter 0000000000000000
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http copy filter: 0 "/trw/?"
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http finalize request: 0, "/trw/?" a:1, c:1
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http request count:1 blk:0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http close request
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 http log handler
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 geoip2 http log handler
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 free: 000056554F3B8F30, unused: 16
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 free: 000056554F4EA170, unused: 2831
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 close http connection: 21
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 reusable connection: 0
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 free: 000056554F386A90
2023/05/01 21:17:26 [debug] 1178497#1178497: *21 free: 000056554F3B8B10, unused: 136
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "Host: x.xxx.com"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "User-Agent: Go-http-client/1.1"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "Connection: Upgrade"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "Sec-WebSocket-Key: Ag7PR0FA6ScauJXwEbe09A=="
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "Sec-WebSocket-Version: 13"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header: "Upgrade: websocket"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http header done
2023/05/01 21:17:26 [info] 1178497#1178497: *22 client sent plain HTTP request to HTTPS port while reading client request headers, client: x.x.x.x, server: x.xxx.com, request: "GET /trw/ HTTP/1.1", host: "x.xxx.com"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http finalize request: 497, "/trw/?" a:1, c:1
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 event timer del: 21: 8338399363
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http special response: 497, "/trw/?"
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 http set discard body
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 xslt filter header
2023/05/01 21:17:26 [debug] 1178497#1178497: *22 HTTP/1.1 400 Bad Request
Server: nginx
Date: Mon, 01 May 2023 21:17:26 GMT
Content-Type: text/html
Content-Length: 248
Connection: close

V2Ray client log (when using utls and Nginx)

2023/05/01 22:01:04 [Warning] [2915757770] app/proxyman/outbound: failed to process outbound traffic > proxy/trojan: failed to find an available destination > common/retry: [transport/internet/websocket: failed 
to dial WebSocket > transport/internet/websocket: failed to dial to (ws://x.xxx.com:443/trw/): 400 Bad Request > websocket: bad handshake] > common/retry: all retry attempts failed  
mydogshitgold commented 1 year ago

Please read the documentation. The uTLS can only be configured using the new v5 configuration format. You will need to rewrite your configuration in the new format or manually patch v2ray-core.


When I use it with tls as security, everything works fine, but when I use 'utls`, nothing works. So, I investigated and found out that Nginx will complain that client sent plain HTTP request to HTTPS port while reading client request headers (Nginx is set up on 443 SSL). Even if I change the security parameter to something gibberish (e.g., "security": "WTF"), it has the same effect, and V2Ray will not complain or crash!

The security attribute only accepts the value tls. Any other value is treated as none, i.e. if you specify utls or any other invalid value, v2ray will not use TLS as transport protocol. Consequently, any data sent over the websocket will be in "cleartext", which could cause such an error.

https://github.com/v2fly/v2ray-core/blob/62bef88a19e76d3a9bb43d92d54942114c6a823d/infra/conf/v4/transport_internet.go#L314

I am worried that even if I discard Nginx and connect two V2Ray directly ("security": "utls" works fine without Nginx between them but I'm not sure if there is any encryption), packets will be transferred without any tls encryption.

However, in the description above, "cleartext" may not be accurate for protocols like vmess and shadowsocks, which encrypt their packets by default and this encryption is not directly related to TLS encryption.


I supposed utls would change the User-agent too, but even with utls, the User-agent is always Go-http-client/1.1, which is easy to exploit and banned.

No. When using TLS/HTTPS, the User-Agent header, like all other headers, is encrypted and protected from eavesdropping and tampering by the middleboxes. It is only visible to the client and the endpoint.

nursery01 commented 1 year ago

No. When using TLS/HTTPS, the User-Agent header, like all other headers, is encrypted and protected from eavesdropping and tampering by the middleboxes. It is only visible to the client and the endpoint.

CDN company can also see it. It may affect the length of the request head.

mydogshitgold commented 1 year ago

No. When using TLS/HTTPS, the User-Agent header, like all other headers, is encrypted and protected from eavesdropping and tampering by the middleboxes. It is only visible to the client and the endpoint.

CDN company can also see it. It may affect the length of the request head.

Yes, CDNs provide a "man-in-the middle as a service" by means of meddling in the decryption of TLS modulation, thus enabling them to execute everyday errands. Unless you uptake for an unethical, untrustworthy, unscrupulous CDN company and utilize an unshielded plaintext proxy protocol, this shouldn't pose a pronounced predicament.

Mahyar24 commented 1 year ago

I read the related issues, but the documentation on V5 configs is immature (at least in English) and lacks examples, making it almost impossible to convert my old-style configs to the new version. I appreciate all the efforts and acknowledge that this project has literally saved dozens of lives during the recent atrocities of the Islamic regime of Iran. However, I have switched to XRay and noticed a huge speedup, but I have no idea why. The only difference between V2Fly and XRay config files is that I am using utls (a.k.a fingerprint).