avn Posted August 15, 2024 Posted August 15, 2024 (edited) Добрый день! Для нормальной работы warp на keenetic хотелось бы реализовать возможность влиять на поле Reserved структуры message_header. По аналогии с командой asc interface {name} wireguard warp {b1} {b2} {b3} У китайцев в Xray-Core получилось это сделать правкой двух методов Xray-core-main\proxy\wireguard\bind.go: func (bind *netBindClient) connectTo(endpoint *netEndpoint) error { c, err := bind.dialer.Dial(bind.ctx, endpoint.dst) if err != nil { return err } endpoint.conn = c go func(readQueue <-chan *netReadInfo, endpoint *netEndpoint) { for { v, ok := <-readQueue if !ok { return } i, err := c.Read(v.buff) if i > 3 { v.buff[1] = 0 v.buff[2] = 0 v.buff[3] = 0 } v.bytes = i v.endpoint = endpoint v.err = err v.waiter.Done() if err != nil && errors.Is(err, io.EOF) { endpoint.conn = nil return } } }(bind.readQueue, endpoint) return nil } func (bind *netBindClient) Send(buff [][]byte, endpoint conn.Endpoint) error { var err error nend, ok := endpoint.(*netEndpoint) if !ok { return conn.ErrWrongEndpointType } if nend.conn == nil { err = bind.connectTo(nend) if err != nil { return err } } for _, buff := range buff { if len(buff) > 3 && len(bind.reserved) == 3 { copy(buff[1:], bind.reserved) } if _, err = nend.conn.Write(buff); err != nil { return err } } return nil } Тестовый конфиг можно получить так: bash -c "$(curl -L warp-reg.vercel.app)" Может и нам можно добавить этот функционал? Edited August 15, 2024 by avn 2 Quote
0 avn Posted August 15, 2024 Author Posted August 15, 2024 А вот и реализация https://gist.github.com/kaseiwang/422d5ef585a1501ac0bde8ccdb76e4f5 Quote
0 Le ecureuil Posted August 16, 2024 Posted August 16, 2024 Я правильно понял, что нужно три байта подствлять в message_header при отправке, и все? Quote
0 avn Posted August 16, 2024 Author Posted August 16, 2024 (edited) 7 часов назад, Le ecureuil сказал: Я правильно понял, что нужно три байта подствлять в message_header при отправке, и все? Да, правильно. Но надо помнить, что эти изменения только стороны клиента (не сервера). Также при коннекте клиентом, они их еще и зануляют. func (bind *netBindClient) connectTo(endpoint *netEndpoint) error { ...... i, err := c.Read(v.buff) if i > 3 { v.buff[1] = 0 v.buff[2] = 0 v.buff[3] = 0 } Вообще, если смотреть конфиг WARP в оригинале, запрошенный через api, то он выглядит так Скрытый текст { "id": "79647", "type": "a", "model": "PC", "name": "FDF5F5", "key": "v9NMcOaNTFw=", "account": { "id": "6714a5c", "account_type": "limited", "created": "2022-12-18T09:54:43.491648Z", "updated": "2024-07-30T12:12:54.223368Z", "premium_data": 139000000000, "quota": 139000000000, "warp_plus": true, "referral_count": 139, "referral_renewal_countdown": 0, "role": "child", "license": "87zW", "ttl": "2024-10-28T12:12:54.047402Z" }, "config": { "client_id": "LHJ3", "peers": [ { "public_key": "bmVo51h2wPfgyo=", "endpoint": { "v4": "188.114.99.229:0", "v6": "[2606:4700:d1::a29f:c30a]:0", "host": "engage.cloudflareclient.com:2408", "ports": [ 854, 859, 864, 878, 880, 890, 891, 894, 903, 908, 928, 934, 939, 942, 943, 945, 946, 955, 968, 987, 988, 1002, 1010, 1014, 1018, 1070, 1074, 1180, 1387, 1843, 2371, 2506, 3138, 3476, 3581, 3854, 4177, 4198, 4233, 5279, 5956, 7103, 7152, 7156, 7281, 7559, 8319, 8742, 8854, 8886 ] } } ], "interface": { "addresses": { "v4": "172.16.0.2", "v6": "2606:4700:110:822e:3e0" } }, "services": { "http_proxy": "172.16.0.1:2480" } }, "warp_enabled": false, "waitlist_enabled": false, "created": "2022-12-18T09:54:43.039543Z", "updated": "2024-08-15T13:45:10.034331432Z", "tos": "2022-12-18T09:54:41.536765Z", "place": 0, "locale": "en-US", "enabled": true, "install_id": "", "fcm_token": "" } Здесь client_id - это "client_id": "LHJ3". Но китайцы раскладывают его на массив из 3 байт. Edited August 16, 2024 by avn Quote
0 avn Posted August 20, 2024 Author Posted August 20, 2024 (edited) Вот еще одна реализация, правда опять на go. Может станет понятнее. Edited August 20, 2024 by avn Quote
0 Le ecureuil Posted August 20, 2024 Posted August 20, 2024 У меня почему-то удаленная сторона WARP с вашим конфигом вообще не отвечает. Потому проверьте на следующей бете сами. Команда interface Wireguard0 wireguard peer <peer> client-id send <value> value - десятеричное число, сделанное простым переводом hex: из 0x1620a6 получается просто 1450150 В итоге в сеть улетает как задумано: 2 Quote
0 avn Posted August 20, 2024 Author Posted August 20, 2024 Спасибо. Обязательно попробую и посмотрю различия в транспорте. Quote
0 Le ecureuil Posted August 21, 2024 Posted August 21, 2024 Вобщем, проверяйте на следующей beta. 2 Quote
0 avn Posted September 4, 2024 Author Posted September 4, 2024 В 21.08.2024 в 13:24, Le ecureuil сказал: Вобщем, проверяйте на следующей beta. Не завелось. Пакеты одинаковые. Слева - keenetic (неуспешно), справа (проходящий трафик) те же настройки (успешно). Я вообще не понимаю, что происходит. Не приходит ни одного пакета обратно. Скрытый текст Трейс (WireShark) - keenetic 1.lkk, проходящий - 3.lkk 1.lkk 3.lkk Quote
0 avn Posted September 4, 2024 Author Posted September 4, 2024 (edited) В 21.08.2024 в 13:24, Le ecureuil сказал: Вобщем, проверяйте на следующей beta. Думаю ошибка где-то здесь, нужно занулить три байта header-а. Мне кажется это подходящее место. Если пойдет прием, значит мы на верном пути. Сейчас прием по нулям. static void wg_packet_consume_data_done(struct wg_peer *peer, struct sk_buff *skb, struct endpoint *endpoint) { ???????????? skb->dev = dev; /* We've already verified the Poly1305 auth tag, which means this packet * was not modified in transit. We can therefore tell the networking * stack that all checksums of every layer of encapsulation have already * been checked "by the hardware" and therefore is unnecessary to check * again in software. */ skb->ip_summed = CHECKSUM_UNNECESSARY; func (b *Bind) NewReceiveFunc(fn conn.ReceiveFunc) conn.ReceiveFunc { return func(buf []byte) (n int, ep conn.Endpoint, err error) { n, ep, err = fn(buf) if err != nil || n < 4 { return } if buf[1] != b.reseved[0] || buf[2] != b.reseved[1] || buf[3] != b.reseved[2] { err = errors.New("bad reseved") return } buf[1] = 0 buf[2] = 0 buf[3] = 0 return } } Edited September 4, 2024 by avn Quote
0 Le ecureuil Posted September 5, 2024 Posted September 5, 2024 Если захват происходит на интерфейсе ISP, то тут вопрос не в Keenetic, что нет ответа. До модуля wg эти пакеты еще даже не дошли в момент захвата, потому что-то занулять бессмысленно, пока не будет ответа в проводе от ISP. Quote
0 Le ecureuil Posted September 5, 2024 Posted September 5, 2024 Посмотрел дампы, разницы не вижу. Видимо что-то еще важно, но непонятно что. Quote
0 avn Posted September 11, 2024 Author Posted September 11, 2024 (edited) Прописал ключи в WireShark. Сразу видно разницу в пакетах. WireShark не может расшифровать пакет с Keenetic Edited September 11, 2024 by avn Quote
0 avn Posted September 11, 2024 Author Posted September 11, 2024 В 05.09.2024 в 10:11, Le ecureuil сказал: Посмотрел дампы, разницы не вижу. Видимо что-то еще важно, но непонятно что. Пересмотрел еще раз патч, смущает кусок с cpu_to_le32 для маски: #define SKB_TYPE_LE32(skb, asc) ((((struct message_header *)(skb)->data)->type) & ((asc) ? 0xFFFFFFFF : cpu_to_le32(0xFF))) Не может он быть корнем проблемы? Quote
0 avn Posted September 15, 2024 Author Posted September 15, 2024 @Le ecureuil У нас WireShark не декодирует пакет. Т.е. mac1 не соответствует данным. if (wg_noise_handshake_create_initiation(&packet, &peer->handshake, wg->advanced_security_config.init_packet_magic_header, peer->client_id)) { wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer); Можете попробовать, сделать присвоение client_id после вызова wg_cookie_add_mac_to_packet() (Т.е. тут wg_noise_handshake_create_initiation client_id не задавать)? Quote
0 avn Posted September 15, 2024 Author Posted September 15, 2024 (edited) 4 часа назад, avn сказал: @Le ecureuil У нас WireShark не декодирует пакет. Т.е. mac1 не соответствует данным. if (wg_noise_handshake_create_initiation(&packet, &peer->handshake, wg->advanced_security_config.init_packet_magic_header, peer->client_id)) { wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer); Можете попробовать, сделать присвоение client_id после вызова wg_cookie_add_mac_to_packet() (Т.е. тут wg_noise_handshake_create_initiation client_id не задавать)? Становится понятен алгоритм. Перед отправкой данных на сервер, уже в готовом пакете данных с рассчитанным mac1 и полем type = 0x00000001 записывается client-id. При получении пакета от сервера, для его успешной расшифровки поле client-id зануляется. Сейчас пакет шифруется в месте с полем client-id. Это приводит к тому, что мы не видим ответов от сервера. Для пакетов с типами 2,3,4 алгоритм такой же. Т.е client-id как бы ещё один уровень транспортного пакета. Перед отправкой установили, при получении сняли. Но во внутренних процессах все работает по старому без client-id. Edited September 15, 2024 by avn Quote
0 Le ecureuil Posted September 15, 2024 Posted September 15, 2024 9 часов назад, avn сказал: @Le ecureuil У нас WireShark не декодирует пакет. Т.е. mac1 не соответствует данным. if (wg_noise_handshake_create_initiation(&packet, &peer->handshake, wg->advanced_security_config.init_packet_magic_header, peer->client_id)) { wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer); Можете попробовать, сделать присвоение client_id после вызова wg_cookie_add_mac_to_packet() (Т.е. тут wg_noise_handshake_create_initiation client_id не задавать)? Ок, перемещу. Вроде все заработало, посмотрите на 4.2.b3. 1 Quote
0 avn Posted September 15, 2024 Author Posted September 15, 2024 2 часа назад, Le ecureuil сказал: Ок, перемещу. Вроде все заработало, посмотрите на 4.2.b3. На b3, или b4 все таки? Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 В 16.09.2024 в 10:22, Le ecureuil сказал: Тьфу, b4 конечно. Работает! Только с ASС не очень дружит. Посмотрю потом на ASC. Браво, спасибо. Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 В 16.09.2024 в 10:22, Le ecureuil сказал: Тьфу, b4 конечно. После снятия asc параметров пришлось роутер перегрузить. Команда не снимает параметры с kernel-space. interface Wireguard2 no wireguard asc Quote
0 Le ecureuil Posted September 19, 2024 Posted September 19, 2024 33 минуты назад, avn сказал: После снятия asc параметров пришлось роутер перегрузить. Команда не снимает параметры с kernel-space. interface Wireguard2 no wireguard asc Проверю, возможно есть такое. Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 (edited) 2 часа назад, Le ecureuil сказал: Проверю, возможно есть такое. Как Вам такая идея для поддержки asc и отправки мусорных пакетов перед коннектом. Для Warp многие задают такие настройки: {jc} {jmin} {jmax} 0 0 1 2 3 4 {jc} {jmin} {jmax} 0 0 0 0 0 0 Заводим еще одну переменную advanced_security_enabled_mask = wg->advanced_security_config.advanced_security_enabled && ( wg->client_id == 0 || wg->advanced_security_config.init_packet_magic_header != MESSAGE_HANDSHAKE_INITIATION || wg->advanced_security_config.response_packet_magic_header != MESSAGE_HANDSHAKE_RESPONSE || wg->advanced_security_config.cookie_packet_magic_header != MESSAGE_HANDSHAKE_COOKIE || wg->advanced_security_config.transport_packet_magic_header != MESSAGE_DATA || wg->advanced_security_config.init_packet_junk_size != 0 || wg->advanced_security_config.response_packet_junk_size != 0) И переделываем вызов макросов на нее #define SKB_TYPE_LE32(skb, asc) ((((struct message_header *)(skb)->data)->type) & ((asc) ? 0xFFFFFFFF : cpu_to_le32(0xFF))) #define SKB_CLEAR_TYPE(skb, asc) ((((struct message_header *)(skb)->data)->type) &= ((asc) ? 0xFFFFFFFF : cpu_to_le32(0xFF))) на: SKB_TYPE_LE32(skb, advanced_security_enabled_mask) SKB_CLEAR_TYPE(skb, advanced_security_enabled_mask) Это позволит использовать asc для Warp и client_id. Edited September 19, 2024 by avn 1 Quote
0 Le ecureuil Posted September 19, 2024 Posted September 19, 2024 Так уже можно использовать asc совместно с client-id, единственное ограничение - что h1/h2/h3/h4 должны быть меньше чем 255 (0xFF). В остальном никаких вопросов. 1 Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 (edited) 55 минут назад, Le ecureuil сказал: Так уже можно использовать asc совместно с client-id, единственное ограничение - что h1/h2/h3/h4 должны быть меньше чем 255 (0xFF). В остальном никаких вопросов. Да, только когда clientid=0. А с заданным значением нельзя. Маска будет раскрываться неправильно. что h1/h2/h3/h4 должны быть меньше чем 255 Тоже работать не будет, только 0 0 0 0 или 1 2 3 4 Это видно из кода wg->advanced_security_config.init_packet_magic_header = MESSAGE_HANDSHAKE_INITIATION; wg->advanced_security_config.response_packet_magic_header = MESSAGE_HANDSHAKE_RESPONSE; wg->advanced_security_config.cookie_packet_magic_header = MESSAGE_HANDSHAKE_COOKIE; wg->advanced_security_config.transport_packet_magic_header = MESSAGE_DATA; Далее, если значение параметра 0, оно не будет перетираться. Сейчас приходит пакет, и он его идентифицировать не может. Т.к. SKB_CLEAR_TYPE не сбросит биты при включенном ASC. А без client_id, они уже = 0. #define SKB_TYPE_LE32(skb, asc) ((((struct message_header *)(skb)->data)->type) & ((asc) ? 0xFFFFFFFF : cpu_to_le32(0xFF))) #define SKB_CLEAR_TYPE(skb, asc) ((((struct message_header *)(skb)->data)->type) &= ((asc) ? 0xFFFFFFFF : cpu_to_le32(0xFF))) static size_t validate_header_len(struct sk_buff *skb, struct wg_device *wg) { __le32 type = 0; if (unlikely(skb->len < sizeof(struct message_header))) return 0; type = SKB_TYPE_LE32(skb, wg->advanced_security_config.advanced_security_enabled); if (type == cpu_to_le32(wg->advanced_security_config.transport_packet_magic_header) && skb->len >= MESSAGE_MINIMUM_LENGTH) return sizeof(struct message_data); if (type == cpu_to_le32(wg->advanced_security_config.init_packet_magic_header) && skb->len == MESSAGE_INITIATION_SIZE) return MESSAGE_INITIATION_SIZE; if (type == cpu_to_le32(wg->advanced_security_config.response_packet_magic_header) && skb->len == MESSAGE_RESPONSE_SIZE) return MESSAGE_RESPONSE_SIZE; if (type == cpu_to_le32(wg->advanced_security_config.cookie_packet_magic_header) && skb->len == MESSAGE_COOKIE_REPLY_SIZE) return MESSAGE_COOKIE_REPLY_SIZE; return 0; Т.е. сейчас обмен с включенным asc выглядит так: typeid = 0x028c284 И протокол его дешифровать не может. Можно попробовать задать параметры 0x018c284 0x028c284 0x038c284 0x048c284, но мне кажется все умрет к чертям Edited September 19, 2024 by avn Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 Ладно, это так мысли можно и без asc жить. Тем более эти настройки сейчас вместе не разрешены. Хотя если сначала задать asc, то можно. Quote
0 Le ecureuil Posted September 19, 2024 Posted September 19, 2024 1 минуту назад, avn сказал: Ладно, это так мысли можно и без asc жить. Тем более эти настройки сейчас вместе не разрешены. Хотя если сначала задать asc, то можно. Попробуйте все же задать параметры с client-id внутри, может и заработает ) Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 (edited) 13 минуты назад, Le ecureuil сказал: Попробуйте все же задать параметры с client-id внутри, может и заработает ) Не работает, т.к. дешифровка пакета не происходит. Я уже трейсы снял. На скриншоте видно. Без ASC все работает отлично. С ASC примерно так: client_id=0x00000. Приходит пакет 0x02000000 SKB_TYPE_LE32 = 0x02000000 & 0xFFFFFFFF = 0x02000000 => MESSAGE_HANDSHAKE_RESPONSE client_id=0x112233. Приходит пакет 0x02112233 SKB_TYPE_LE32 = 0x02112233 & 0xFFFFFFFF = 0x02112233 !=> MESSAGE_HANDSHAKE_RESPONSE ASC выключен: client_id=0x00000. Приходит пакет 0x02000000 SKB_TYPE_LE32 = 0x02000000 & 0xFF000000 = 0x02000000 => MESSAGE_HANDSHAKE_RESPONSE client_id=0x112233. Приходит пакет 0x02112233 SKB_TYPE_LE32 = 0x02112233 & 0xFF000000= 0x02000000 => MESSAGE_HANDSHAKE_RESPONSE Edited September 19, 2024 by avn Quote
0 avn Posted September 19, 2024 Author Posted September 19, 2024 Оставлю комментарий для себя на будущее. Думаю, что проблема в цепочке wg_packet_receive->prepare_skb_header->validate_header_len. validate_header_len возвращает 0. И далее все падает. Quote
0 Le ecureuil Posted September 26, 2024 Posted September 26, 2024 Сделал. Теперь если h1/h2/h3/h4 меньше или равны 0xFF, то сосуществование с client-id работает. Если хоть один из них больше - работает только ASC. 5 Quote
Question
avn
Добрый день!
Для нормальной работы warp на keenetic хотелось бы реализовать возможность влиять на поле Reserved структуры message_header.
По аналогии с командой asc
interface {name} wireguard warp {b1} {b2} {b3}
У китайцев в Xray-Core получилось это сделать правкой двух методов Xray-core-main\proxy\wireguard\bind.go:
func (bind *netBindClient) connectTo(endpoint *netEndpoint) error { c, err := bind.dialer.Dial(bind.ctx, endpoint.dst) if err != nil { return err } endpoint.conn = c go func(readQueue <-chan *netReadInfo, endpoint *netEndpoint) { for { v, ok := <-readQueue if !ok { return } i, err := c.Read(v.buff) if i > 3 { v.buff[1] = 0 v.buff[2] = 0 v.buff[3] = 0 } v.bytes = i v.endpoint = endpoint v.err = err v.waiter.Done() if err != nil && errors.Is(err, io.EOF) { endpoint.conn = nil return } } }(bind.readQueue, endpoint) return nil } func (bind *netBindClient) Send(buff [][]byte, endpoint conn.Endpoint) error { var err error nend, ok := endpoint.(*netEndpoint) if !ok { return conn.ErrWrongEndpointType } if nend.conn == nil { err = bind.connectTo(nend) if err != nil { return err } } for _, buff := range buff { if len(buff) > 3 && len(bind.reserved) == 3 { copy(buff[1:], bind.reserved) } if _, err = nend.conn.Write(buff); err != nil { return err } } return nil }
Тестовый конфиг можно получить так:
bash -c "$(curl -L warp-reg.vercel.app)"
Может и нам можно добавить этот функционал?
Edited by avn31 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.