fix: -obf-timing допустим только с -mode udp и включённой обфускацией

без RTP-профиля паковать нечего, а в tcp-режиме pacing ломает RTT/конгешн
KCP. Раньше флаг в tcp молча игнорировался. Валидация симметрична на
клиенте и сервере.
This commit is contained in:
samosvalishe
2026-06-19 15:09:41 +03:00
parent bafdcdd027
commit e50febc834
2 changed files with 60 additions and 1 deletions
+21
View File
@@ -373,6 +373,9 @@ func ParseClient(args []string, errOut io.Writer) (*Client, error) {
return nil, err
}
c.Obf.Key = key
if err := validateObfTiming(c.Obf, c.Proxy.Mode); err != nil {
return nil, err
}
if c.TURN.N <= 0 {
c.TURN.N = 10
}
@@ -443,10 +446,28 @@ func ParseServer(args []string, errOut io.Writer) (*Server, error) {
return nil, err
}
s.Obf.Key = key
if err := validateObfTiming(s.Obf, s.Proxy.Mode); err != nil {
return nil, err
}
return s, nil
}
// validateObfTiming ограничивает -obf-timing UDP-релеем с включённой обфускацией:
// без RTP-профиля паковать нечего, а в tcp-режиме pacing ломает RTT/конгешн KCP.
func validateObfTiming(o ObfOpts, mode ProxyMode) error {
if o.Timing <= 0 {
return nil
}
if !o.Enabled() {
return errors.New("-obf-timing requires -obf-profile != none")
}
if mode != ProxyModeUDP {
return errors.New("-obf-timing supported only with -mode udp")
}
return nil
}
// validateObfProfile проверяет что -obf-profile содержит известное значение.
func validateObfProfile(p ObfProfile) error {
switch p {
+39 -1
View File
@@ -7,8 +7,11 @@ import (
"io"
"strings"
"testing"
"time"
)
const testObfKey = "0000000000000000000000000000000000000000000000000000000000000000"
func validClientArgs() []string {
return []string{
"-peer", "1.2.3.4:5000",
@@ -99,7 +102,7 @@ func TestParseClient_MultiLinks(t *testing.T) {
func TestParseClient_MissingVKLink(t *testing.T) {
_, err := ParseClient([]string{"-peer", "1.2.3.4:5000"}, io.Discard)
if err == nil || !(strings.Contains(err.Error(), "-links") || strings.Contains(err.Error(), "-link")) {
if err == nil || (!strings.Contains(err.Error(), "-links") && !strings.Contains(err.Error(), "-link")) {
t.Errorf("expected vk-link error, got %v", err)
}
}
@@ -153,6 +156,41 @@ func TestParseClient_ObfProfileInvalid(t *testing.T) {
}
}
func TestParseClient_ObfTimingRequiresObf(t *testing.T) {
args := append(validClientArgs(), "-obf-timing", "20ms")
_, err := ParseClient(args, io.Discard)
if err == nil || !strings.Contains(err.Error(), "-obf-timing") {
t.Errorf("expected obf-timing error without profile, got %v", err)
}
}
func TestParseClient_ObfTimingRejectsTCP(t *testing.T) {
args := append(validClientArgs(), "-mode", "tcp", "-obf-profile", "rtpopus3", "-obf-key", testObfKey, "-obf-timing", "20ms")
_, err := ParseClient(args, io.Discard)
if err == nil || !strings.Contains(err.Error(), "-obf-timing") {
t.Errorf("expected obf-timing/mode error, got %v", err)
}
}
func TestParseClient_ObfTimingValid(t *testing.T) {
args := append(validClientArgs(), "-obf-profile", "rtpopus3", "-obf-key", testObfKey, "-obf-timing", "20ms")
c, err := ParseClient(args, io.Discard)
if err != nil {
t.Fatal(err)
}
if c.Obf.Timing != 20*time.Millisecond {
t.Errorf("Obf.Timing = %v, want 20ms", c.Obf.Timing)
}
}
func TestParseServer_ObfTimingRejectsTCP(t *testing.T) {
args := []string{"-connect", "127.0.0.1:51820", "-mode", "tcp", "-obf-profile", "rtpopus3", "-obf-key", testObfKey, "-obf-timing", "10ms"}
_, err := ParseServer(args, io.Discard)
if err == nil || !strings.Contains(err.Error(), "-obf-timing") {
t.Errorf("expected obf-timing/mode error, got %v", err)
}
}
func TestParseClient_StreamsPerCredNonPositive(t *testing.T) {
args := append(validClientArgs(), "-streams-per-cred", "0")
_, err := ParseClient(args, io.Discard)