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

Added tcp fragmentation for freedom outbound #2021

Merged
merged 6 commits into from
May 22, 2023
Merged

Added tcp fragmentation for freedom outbound #2021

merged 6 commits into from
May 22, 2023

Conversation

sambali9
Copy link
Contributor

@sambali9 sambali9 commented May 2, 2023

This is inspired by https://github.com/GFW-knocker/gfw_resist_tls_proxy
Usage:

{
    "protocol": "freedom",
    "settings": {
        "fragment": {
            "delay": 100, // Delay after each fragment
            "divider": 10, // Number of packets to send, if the original packet size is not divisible by the divider the last packet will be fragment + remainder
            "packetNumber": 1 // nth packet to fragment, if 0 all outbound packets will be fragmented
        }
    }
}

@yuhan6665
Copy link
Member

@RPRX

@RPRX
Copy link
Member

RPRX commented May 3, 2023

感谢 PR,建议如下:

  1. 需设置 TCP_NODELAY
  2. delay 改名为 interval,可以设置一个范围,每次随机,比如 "interval": "100-300"(与 REALITY 的 spiderX 类似)
  3. 或许将策略改为指定每次发送的长度更好?比如 "50-100",每次发送 50-100 bytes

@sambali9
Copy link
Contributor Author

sambali9 commented May 3, 2023

Usage:

{
    "protocol": "freedom",
    "settings": {
        "fragment": {
           "length": "10-20", // length of each fragment to send in bytes. It can be single value or range it has to be a string. If it is a range the values are randomly chosen.
            "interval": "100-500", // the time to wait for each packet in milliseconds. Can be single value or range but it has to be a string. If it is a range the values are randomly chosen.
            "packetNumber": 1 // nth packet to fragment, if 0 all outbound packets will be fragmented
        }
    },
    "streamSettings": {
        "sockopt": {
            "tcpNoDelay": true // This needs to be enabled so the kernel doesn't cache the fragments
        }
    }
}

@RPRX
Copy link
Member

RPRX commented May 4, 2023

感谢,既然另外两个参数都是 "x-y" 的形式了,我们也可以设置 "packets": "1-3",它的含义为前三个包,这样更灵活一些

此项为 "" 时,all outbound packets will be fragmented

此外我想知道,目前这个 PR 的代码在伊朗是否有效,比如可以直接上 youtube?

@RPRX
Copy link
Member

RPRX commented May 4, 2023

"packets": "0-3" 这种直接报错

@sambali9
Copy link
Contributor Author

sambali9 commented May 4, 2023

In Iran the censorship system is not centralised and results can vary from different ISPs. For me I couldn't get www.youtube.com to work but it worked with sites behind Cloudflare like www.clubhouseapi.com which was blocked without fragmentation. The setting that worked:

{
            "protocol": "freedom",
            "settings": {
                "fragment": {
                    "length": "1-10",
                    "interval": "10-100",
                    "packetNumber": 1
                }
            },
            "streamSettings": {
                "sockopt": {
                    "tcpNoDelay": true
                }
            }
}

I didn't understand what you meant with "packets": "1-3", should this match the first, second and the third packet or is it gonna be like go slices where this matches the second and the third packets?

@RPRX
Copy link
Member

RPRX commented May 4, 2023

I didn't understand what you meant with "packets": "1-3", should this match the first, second and the third packet or is it gonna be like go slices where this matches the second and the third packets?

The first, second and the third packet.

@RPRX
Copy link
Member

RPRX commented May 4, 2023

The order should be like:

type Fragment struct {
	Packets  string `json:"packets"`
	Length   string `json:"length"`
	Interval string `json:"interval"`
}

@mortada-jafar
Copy link

mortada-jafar commented May 4, 2023

"packets": "0-3"This kind of direct error

I tested it not work!
dirty IP: connection is established but the upload speed has been throttled.
clean IP: working.

Network Provider: MCI
please check my test example @sambali9

"outbounds": [
    {
      "mux": {
        "concurrency": 8,
        "enabled": false
      },
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "162.159.135.42", // dirty ip
            "port": 443,
            "users": [
              {
                "alterId": 0,
                "encryption": "",
                "flow": "",
                "id": "75312dc8-20b8-4b3f-b006-e69553cf1e34",
                "level": 8,
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "tlsSettings": {
          "allowInsecure": false,
          "fingerprint": "",
          "publicKey": "",
          "serverName": "ServerDomain",
          "shortId": "",
          "show": false,
          "spiderX": ""
        },
        "wsSettings": {
          "headers": {
            "Host": "ServerDomain"
          },
          "path": "/"
        }
      },
      "tag": "proxy"
    },
    {
      "protocol": "freedom",
      "settings": {
        "fragment": {
          "length": "1-10",
          "interval": "10-100",
          "packetNumber": 1
        }
      },
      "streamSettings": {
        "sockopt": {
          "tcpNoDelay": true
        }
      }
    }
  ]

@sambali9
Copy link
Contributor Author

sambali9 commented May 4, 2023

dirty IP: connection is established but the upload speed has been throttled.

Do you get good result with python scripts at gfw_resist_tls_proxy?
If you get good result please provide your configurations (packet length and delay time).

آپلودتون با اسکریپت های gfw_resist_tls_proxy خوبه؟
اگر آپلودتون با نسخه پایتون خوب هست لطفا مقادیر مثل اندازه پکت ها و زمان بینشون رو بنویسید.

@mortada-jafar
Copy link

mortada-jafar commented May 4, 2023

same as gfw_resist_tls_proxy
خیر الان تست کردم فرقی ندارد

i think they detected this method

@hiddify-com
Copy link
Contributor

It is great. it would be greater if you add it for all outbounds not only the freedom outbound

@sambali9
Copy link
Contributor Author

sambali9 commented May 5, 2023

It is great. it would be greater if you add it for all outbounds not only the freedom outbound

There is actually no need to do that. You can simply use the dialerProxy to do with other outbounds:

"outbounds": [
        {
            "protocol": "vmess",
            "settings": {
                "vnext": [
                    {
                        "address": "1.2.3.4",
                        "port": 1234,
                        "users": [
                            {
                                "id": "5e0fa60c-0074-4ca7-87c2-3a1af806e89e",
                                "level": 0
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "sockopt": {
                    "dialerProxy": "fragment"
                }
            },
            "tag": "proxy"
        },
        {
            "protocol": "freedom",
            "settings": {
                "fragment": {
                    "length": "1",
                    "interval": "100-150",
                    "packets": "1-3"
                }
            },
            "streamSettings": {
                "sockopt": {
                    "tcpNoDelay": true
                }
            },
            "tag": "fragment"
        }
    ]

@sambali9
Copy link
Contributor Author

sambali9 commented May 5, 2023

@RPRX BTW in case you didn't notice I have changed the packetNumber to packets as requested

@sambali9
Copy link
Contributor Author

sambali9 commented May 5, 2023

Usage:

{
    "protocol": "freedom",
    "settings": {
        "fragment": {
           "length": "10-20", // length of each fragment to send in bytes. It can be single value or range it has to be a string. If it is a range the values are randomly chosen.
            "interval": "100-500", // the time to wait for each packet in milliseconds. Can be single value or range but it has to be a string. If it is a range the values are randomly chosen.
            "packets": "1-3" // nth packet(s) to fragment, if empty all outbound packets will be fragmented, can be a single number or a range. The start packet cannot be 0 so 0-3 is not acceptable. The range numbers are inclusive.
        }
    },
    "streamSettings": {
        "sockopt": {
            "tcpNoDelay": true // This needs to be enabled so the kernel doesn't cache the fragments
        }
    }
}

Usage with other outbounds:

The outbound proxy has to be the first in outbounds array and using the dialerProxy it is possible to fragment the proxy packets after their encodings:

"outbounds": [
        {
            "protocol": "vmess", // the proxy has to be first so our request is encoded by our protocol first
            "settings": {
                "vnext": [
                    {
                        "address": "1.2.3.4",
                        "port": 1234,
                        "users": [
                            {
                                "id": "5e0fa60c-0074-4ca7-87c2-3a1af806e89e",
                                "level": 0
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "sockopt": {
                    "dialerProxy": "fragment" // after the request has been encoded by our protocol (here is vmess) the request is then sent through our freedom outbound with fragmentation on.
                }
            },
            "tag": "proxy"
        },
        {
            "protocol": "freedom",
            "settings": {
                "fragment": {
                    "length": "1",
                    "interval": "100-150",
                    "packets": "1-3"
                }
            },
            "streamSettings": {
                "sockopt": {
                    "tcpNoDelay": true
                }
            },
            "tag": "fragment" // this tag name is used to pass to the dialerProxy above
        }
    ]

proxy/freedom/freedom.go Outdated Show resolved Hide resolved
proxy/freedom/freedom.go Outdated Show resolved Hide resolved
proxy/freedom/freedom.go Outdated Show resolved Hide resolved
proxy/freedom/freedom.go Outdated Show resolved Hide resolved
@RPRX
Copy link
Member

RPRX commented May 6, 2023

感谢!以上是一些使代码逻辑更清晰的建议

@RPRX
Copy link
Member

RPRX commented May 6, 2023

合并这个 PR 后,计划给 WSS 的 path 添加一些参数以支持快速配置与分享 #2000 (comment)

@A5DkjGQUZx
Copy link

Great work... KUDOS TO ALL

@weareomid
Copy link

Why is it not merged yet?

@A5DkjGQUZx
Copy link

Why is it not merged yet?

You can try binaries with the new features here: https://github.com/XTLS/Xray-core/actions/runs/4901135431

How to config?! #2021 (comment)

@RPRX
Copy link
Member

RPRX commented May 21, 2023

感谢 PR,考虑到伊朗的情况,v1.8.2 将包含这个 PR 的内容

@RPRX RPRX merged commit 5f5ae37 into XTLS:main May 22, 2023
omengye added a commit to omengye/Xray-core that referenced this pull request May 22, 2023
Added tcp fragmentation for freedom outbound (XTLS#2021)
@WordsWorthLess
Copy link

Why is it not merged yet?

You can try binaries with the new features here: https://github.com/XTLS/Xray-core/actions/runs/4901135431

How to config?! #2021 (comment)

Why is it not merged yet?

You can try binaries with the new features here: https://github.com/XTLS/Xray-core/actions/runs/4901135431

How to config?! #2021 (comment)

Tried it with websocket/gRPC with CloudFlare CDN
config:

		{
			"tag": "ws_fragmentation",
			"sendThrough": "::",
			"protocol": "vless",
			"settings": {
				"vnext": [
					{
						"address": "cloudflare_ip",
						"port": 443,
						"users": [
							{
								"id": "uuid",
								"encryption": "none"
							}
						]
					}
				]
			},
			"streamSettings": {
				"network": "ws",
				"security": "tls",
				"tlsSettings": {
					"serverName": "server.name",
					"alpn": [
						"http/1.1"
					],
					"allowInsecure": false
				},
				"wsSettings": {
					"path": "/wspath"
				},
				"sockopt": {
					"domainStrategy": "AsIs",
					"dialerProxy": "fragment",
					"mark": 255
				}
			}
		},
		{
			"tag": "fragment",
			"protocol": "freedom",
			"settings": {
				"fragment": {
					"length": "8-15",
					"interval": "50-250",
					"packets": "1-3"
				}
			},
			"streamSettings": {
				"sockopt": {
					"tcpNoDelay": true,
					"mark": 255
				}
			}

And I got TCP RST

@H1JK
Copy link
Member

H1JK commented May 29, 2023

In fact, Go enables TCPNoDelay by default (see documentation).

https://pkg.go.dev/net#TCPConn.SetNoDelay

@SasukeFreestyle
Copy link

SasukeFreestyle commented Jun 8, 2023

Can anyone provide client and server configuration for this for VLESS-Vision Reality TCP

Thanks

@A5DkjGQUZx
Copy link

You can try binaries with the new features here: https://github.com/XTLS/Xray-core/actions/runs/4901135431

How to config?! #2021 (comment)

You can try binaries with the new features here: https://github.com/XTLS/Xray-core/actions/runs/4901135431
How to config?! #2021 (comment)

@ahmadrezaei
Copy link

How we can use it in Dokodemo-Door ?

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

Successfully merging this pull request may close these issues.