Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-20 16:25:49 +00:00

23 Commits

Author SHA1 Message Date
bol-van
6638140880 zapret-auto: instances arg in condition, cond_lua 2026-02-09 17:24:11 +03:00
bol-van
41bac1833e nfqws2: remove bind to address in rawsend 2026-02-09 15:59:53 +03:00
bol-van
c3b1cc3eb9 update docs 2026-02-09 13:45:23 +03:00
bol-van
6f52fb08f9 update docs 2026-02-09 13:44:41 +03:00
bol-van
08549b570b update docs 2026-02-09 13:43:46 +03:00
bol-van
13daef5167 update docs 2026-02-09 13:39:26 +03:00
bol-van
1fd6063cd7 update docs 2026-02-09 13:38:25 +03:00
bol-van
5e4f78228e zapret-auto: per_instance_condition not execute if cond arg absent 2026-02-09 13:28:51 +03:00
bol-van
2e255ca59f zapret-auto: per_instance_condition 2026-02-09 13:19:01 +03:00
bol-van
565a8abffc AI fixes 2026-02-09 10:04:13 +03:00
bol-van
69f1576f7e AI fixes 2026-02-08 17:22:39 +03:00
bol-van
0917cb21bb AI fixes 2026-02-08 17:12:36 +03:00
bol-van
8f316ae1a2 nfqws2: AI fixes 2026-02-07 20:07:49 +03:00
bol-van
caaf5e7a2e nfqws2: DLOG_ERR payload too large 2026-02-07 14:50:54 +03:00
bol-van
dbfbd6e6d3 nfqws2: DLOG_ERR if payload does not fit into the buffer 2026-02-07 14:47:31 +03:00
bol-van
397fe60b5f update docs 2026-02-07 13:55:23 +03:00
bol-van
e096ed64bc update docs 2026-02-07 13:54:01 +03:00
bol-van
0f2def9bd5 update docs 2026-02-07 13:52:11 +03:00
bol-van
85721e4b82 update docs 2026-02-07 13:50:55 +03:00
bol-van
0fd9314df9 update docs 2026-02-07 13:49:54 +03:00
bol-van
a9e2bfe49c update docs 2026-02-07 13:48:27 +03:00
bol-van
bd7a40f5a9 nfqws2: handling of incoming frag, AI fixes 2026-02-07 13:36:31 +03:00
bol-van
bcd50f5215 zapret-tests: 64-bit time support checks 2026-02-06 17:16:40 +03:00
20 changed files with 693 additions and 426 deletions

View File

@@ -228,3 +228,11 @@ nfqws2: bt and utp_bt protocol detectors
nfqws2: localtime,gmtime,timelocal,timegm luacalls
winws2: load wlanapi.dll dynamically only if needed
winws2: fixed lost windivert deinit on logical network disappear
0.9.3
nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
zapret-auto: per_instance_condition orchestrator
zapret-auto: "instances" argument in condition orchestrator
zapret-auto: cond_tcp_has_ts, cond_lua iff functions
zapret-lib: replay_execution_plan and plan_clear max parameter

View File

@@ -59,21 +59,21 @@
- [Random Data Generation](#random-data-generation)
- [brandom](#brandom)
- [Parsing](#parsing)
- [parse\_hex](#parse_hex)
- [parse_hex](#parse_hex)
- [Cryptography](#cryptography)
- [bcryptorandom](#bcryptorandom)
- [bxor,bor,band](#bxorborband)
- [hash](#hash)
- [aes](#aes)
- [aes\_gcm](#aes_gcm)
- [aes\_ctr](#aes_ctr)
- [aes_gcm](#aes_gcm)
- [aes_ctr](#aes_ctr)
- [hkdf](#hkdf)
- [Compression](#compression)
- [gunzip](#gunzip)
- [gzip](#gzip)
- [System functions](#system-functions)
- [uname](#uname)
- [clock\_gettime](#clock_gettime)
- [clock_gettime](#clock_gettime)
- [getpid](#getpid)
- [stat](#stat)
- [time](#time)
@@ -82,23 +82,23 @@
- [standard rawsend](#standard-rawsend)
- [Dissection and reconstruction](#dissection-and-reconstruction)
- [dissect](#dissect)
- [reconstruct\_dissect](#reconstruct_dissect)
- [reconstruct\_hdr](#reconstruct_hdr)
- [csum\_fix](#csum_fix)
- [reconstruct_dissect](#reconstruct_dissect)
- [reconstruct_hdr](#reconstruct_hdr)
- [csum_fix](#csum_fix)
- [conntrack](#conntrack)
- [Obtaining IP addresses](#obtaining-ip-addresses)
- [Receiving and sending Packets](#receiving-and-sending-packets)
- [rawsend](#rawsend)
- [raw\_packet](#raw_packet)
- [raw_packet](#raw_packet)
- [Working with payloads](#working-with-payloads)
- [Markers](#markers)
- [resolve\_pos](#resolve_pos)
- [tls\_mod](#tls_mod)
- [resolve_pos](#resolve_pos)
- [tls_mod](#tls_mod)
- [Instance execution management](#instance-execution-management)
- [instance\_cutoff](#instance_cutoff)
- [lua\_cutoff](#lua_cutoff)
- [execution\_plan](#execution_plan)
- [execution\_plan\_cancel](#execution_plan_cancel)
- [instance_cutoff](#instance_cutoff)
- [lua_cutoff](#lua_cutoff)
- [execution_plan](#execution_plan)
- [execution_plan_cancel](#execution_plan_cancel)
- [zapret-lib.lua base function library](#zapret-liblua-base-function-library)
- [Base desync functions](#base-desync-functions)
- [luaexec](#luaexec)
@@ -106,16 +106,16 @@
- [pktdebug](#pktdebug)
- [argdebug](#argdebug)
- [posdebug](#posdebug)
- [detect\_payload\_str](#detect_payload_str)
- [desync\_orchestrator\_example](#desync_orchestrator_example)
- [detect_payload_str](#detect_payload_str)
- [desync_orchestrator_example](#desync_orchestrator_example)
- [Utility functions](#utility-functions)
- [var\_debug](#var_debug)
- [var_debug](#var_debug)
- [deepcopy](#deepcopy)
- [logical\_xor](#logical_xor)
- [array\_search](#array_search)
- [logical_xor](#logical_xor)
- [array_search](#array_search)
- [String operations](#string-operations)
- [in\_list](#in_list)
- [find\_next\_line](#find_next_line)
- [in_list](#in_list)
- [find_next_line](#find_next_line)
- [Raw string handling](#raw-string-handling)
- [hex](#hex)
- [pattern](#pattern)
@@ -123,18 +123,18 @@
- [TCP sequence number handling](#tcp-sequence-number-handling)
- [Position handling](#position-handling)
- [Dissection](#dissection)
- [dissect\_url](#dissect_url)
- [dissect\_nld](#dissect_nld)
- [dissect\_http](#dissect_http)
- [dissect\_tls](#dissect_tls)
- [dissect_url](#dissect_url)
- [dissect_nld](#dissect_nld)
- [dissect_http](#dissect_http)
- [dissect_tls](#dissect_tls)
- [Working with L3 and L4 protocol elements](#working-with-l3-and-l4-protocol-elements)
- [find\_tcp\_options](#find_tcp_options)
- [find_tcp_options](#find_tcp_options)
- [ip6hdr](#ip6hdr)
- [ip protocol](#ip-protocol)
- [packet\_len](#packet_len)
- [packet_len](#packet_len)
- [Working with hostnames](#working-with-hostnames)
- [genhost](#genhost)
- [host\_ip](#host_ip)
- [host_ip](#host_ip)
- [File name and path operations](#file-name-and-path-operations)
- [Reading and writing Files](#reading-and-writing-files)
- [Data compression](#data-compression)
@@ -143,29 +143,29 @@
- [standard ipid](#standard-ipid)
- [standard fooling](#standard-fooling)
- [standard ipfrag](#standard-ipfrag)
- [apply\_ip\_id](#apply_ip_id)
- [apply\_fooling](#apply_fooling)
- [apply_ip_id](#apply_ip_id)
- [apply_fooling](#apply_fooling)
- [ipfrag2](#ipfrag2)
- [wssize\_rewrite](#wssize_rewrite)
- [dis\_reverse](#dis_reverse)
- [wssize_rewrite](#wssize_rewrite)
- [dis_reverse](#dis_reverse)
- [IP addresses and interfaces](#ip-addresses-and-interfaces)
- [Sending](#sending)
- [rawsend\_dissect\_ipfrag](#rawsend_dissect_ipfrag)
- [rawsend\_dissect\_segmented](#rawsend_dissect_segmented)
- [rawsend\_payload\_segmented](#rawsend_payload_segmented)
- [rawsend_dissect_ipfrag](#rawsend_dissect_ipfrag)
- [rawsend_dissect_segmented](#rawsend_dissect_segmented)
- [rawsend_payload_segmented](#rawsend_payload_segmented)
- [Standard direction and payload filters](#standard-direction-and-payload-filters)
- [Working with multi-packet payloads](#working-with-multi-packet-payloads)
- [Orchestration](#orchestration)
- [instance\_cutoff\_shim](#instance_cutoff_shim)
- [cutoff\_shim\_check](#cutoff_shim_check)
- [apply\_arg\_prefix](#apply_arg_prefix)
- [apply\_execution\_plan](#apply_execution_plan)
- [verdict\_aggregate](#verdict_aggregate)
- [plan\_instance\_execute](#plan_instance_execute)
- [plan\_instance\_pop](#plan_instance_pop)
- [plan\_clear](#plan_clear)
- [instance_cutoff_shim](#instance_cutoff_shim)
- [cutoff_shim_check](#cutoff_shim_check)
- [apply_arg_prefix](#apply_arg_prefix)
- [apply_execution_plan](#apply_execution_plan)
- [verdict_aggregate](#verdict_aggregate)
- [plan_instance_execute](#plan_instance_execute)
- [plan_instance_pop](#plan_instance_pop)
- [plan_clear](#plan_clear)
- [orchestrate](#orchestrate)
- [replay\_execution\_plan](#replay_execution_plan)
- [replay_execution_plan](#replay_execution_plan)
- [zapret-antidpi.lua DPI attack program library](#zapret-antidpilua-dpi-attack-program-library)
- [Standard parameter sets](#standard-parameter-sets)
- [standard direction](#standard-direction)
@@ -175,22 +175,22 @@
- [send](#send)
- [pktmod](#pktmod)
- [HTTP fooling](#http-fooling)
- [http\_hostcase](#http_hostcase)
- [http\_domcase](#http_domcase)
- [http\_methodeol](#http_methodeol)
- [http\_unixeol](#http_unixeol)
- [http_hostcase](#http_hostcase)
- [http_domcase](#http_domcase)
- [http_methodeol](#http_methodeol)
- [http_unixeol](#http_unixeol)
- [Window size replacement](#window-size-replacement)
- [wsize](#wsize)
- [wssize](#wssize)
- [Fakes](#fakes)
- [syndata](#syndata)
- [tls\_client\_hello\_clone](#tls_client_hello_clone)
- [tls_client_hello_clone](#tls_client_hello_clone)
- [fake](#fake)
- [rst](#rst)
- [TCP segmentation](#tcp-segmentation)
- [multisplit](#multisplit)
- [multidisorder](#multidisorder)
- [multidisorder\_legacy](#multidisorder_legacy)
- [multidisorder_legacy](#multidisorder_legacy)
- [fakedsplit](#fakedsplit)
- [fakeddisorder](#fakeddisorder)
- [hostfakesplit](#hostfakesplit)
@@ -198,32 +198,35 @@
- [oob](#oob)
- [UDP Fooling](#udp-fooling)
- [udplen](#udplen)
- [dht\_dn](#dht_dn)
- [dht_dn](#dht_dn)
- [Other Functions](#other-functions)
- [synack](#synack)
- [synack\_split](#synack_split)
- [synack_split](#synack_split)
- [zapret-auto.lua automation and orchestration library](#zapret-autolua-automation-and-orchestration-library)
- [State storage](#state-storage)
- [automate\_conn\_record](#automate_conn_record)
- [standard\_hostkey](#standard_hostkey)
- [automate\_host\_record](#automate_host_record)
- [automate_conn_record](#automate_conn_record)
- [standard_hostkey](#standard_hostkey)
- [automate_host_record](#automate_host_record)
- [Handling successes and failures](#handling-successes-and-failures)
- [automate\_failure\_counter](#automate_failure_counter)
- [automate\_failure\_counter\_reset](#automate_failure_counter_reset)
- [automate_failure_counter](#automate_failure_counter)
- [automate_failure_counter_reset](#automate_failure_counter_reset)
- [Success and failure detection](#success-and-failure-detection)
- [automate\_failure\_check](#automate_failure_check)
- [standard\_success\_detector](#standard_success_detector)
- [standard\_failure\_detector](#standard_failure_detector)
- [automate_failure_check](#automate_failure_check)
- [standard_success_detector](#standard_success_detector)
- [standard_failure_detector](#standard_failure_detector)
- [Orchestrators](#orchestrators)
- [circular](#circular)
- [repeater](#repeater)
- [condition](#condition)
- [per_instance_condition](#per_instance_condition)
- [stopif](#stopif)
- [iff functions](#iff-functions)
- [cond\_true](#cond_true)
- [cond\_false](#cond_false)
- [cond\_random](#cond_random)
- [cond\_payload\_str](#cond_payload_str)
- [cond_true](#cond_true)
- [cond_false](#cond_false)
- [cond_random](#cond_random)
- [cond_payload_str](#cond_payload_str)
- [cond_tcp_has_ts](#cond_tcp_has_ts)
- [cond_lua](#cond_lua)
- [Auxiliary programs](#auxiliary-programs)
- [ip2net](#ip2net)
- [mdig](#mdig)
@@ -247,16 +250,16 @@
- [List management system](#list-management-system)
- [Standard list files](#standard-list-files)
- [ipset scripts](#ipset-scripts)
- [clear\_lists.sh](#clear_listssh)
- [create\_ipset.sh](#create_ipsetsh)
- [get\_config.sh](#get_configsh)
- [get\_user.sh](#get_usersh)
- [get\_ipban.sh](#get_ipbansh)
- [get\_exclude.sh](#get_excludesh)
- [get\_antifilter\_\*.sh](#get_antifilter_sh)
- [get\_antizapret\_domains.sh](#get_antizapret_domainssh)
- [get\_refilter\_\*.sh](#get_refilter_sh)
- [get\_reestr\_\*.sh](#get_reestr_sh)
- [clear_lists.sh](#clear_listssh)
- [create_ipset.sh](#create_ipsetsh)
- [get_config.sh](#get_configsh)
- [get_user.sh](#get_usersh)
- [get_ipban.sh](#get_ipbansh)
- [get_exclude.sh](#get_excludesh)
- [get_antifilter_*.sh](#get_antifilter_sh)
- [get_antizapret_domains.sh](#get_antizapret_domainssh)
- [get_refilter_*.sh](#get_refilter_sh)
- [get_reestr_*.sh](#get_reestr_sh)
- [ipban system](#ipban-system)
- [Init scripts](#init-scripts)
- [Firewall integration](#firewall-integration)
@@ -1390,6 +1393,7 @@ All multi-byte numeric values are automatically converted from network byte orde
| :------------ | :----- | :--------------------------------------------------------------- |
| ip | table | IPv4 header |
| ip6 | table | IPv6 header |
| frag_off | number | IP fragment offset. present only in IP fragments. |
| tcp | table | TCP header |
| udp | table | UDP header |
| icmp | table | ICMP header |
@@ -2098,10 +2102,12 @@ Those functions receive an already prepared dissect.
function reconstruct_dissect(dissect[, reconstruct_opts])
```
Returns `raw_ip`. All checksums are calculated automatically. L4 checksums are intentionally corrupted if `badsum` is specified in `reconstruct_opts`.
Returns `raw_ip`. All checksums are calculated automatically. L4 checksums are intentionally corrupted if `badsum` is specified in [reconstruct_opts](#standard-reconstruct).
Reconstructing dissects with IP fragmentation involves a specific interaction between Lua and C code.
The Lua code must prepare a dissect of the full packet intended for fragmentation, but fill certain fields as they should appear in the fragment:
Reconstruction of fragmented IP packets involves special magic.
1. if the "frag_off" field is present, tcp/udp/icmp headers are ignored, payload contains raw ip payload. Incoming fragmented packets come in this form. nfqws2 does not defragment at the IP layer. But this is very persistently done by Linux systems - in order for a fragment to come to nfqws2, you need to try hard by inserting "notrack" into prerouting or output. Dissects in this form can be reconstructed as is. But preparing them in Lua is extremely inconvenient, since you will have to go through the black magic of working with a binary representation.
2. If the "frag_off" field is absent, fragment reconstruction is performed on the entire packet's dissect involving both Lua and C code. Lua code must prepare a dissect of the full packet intended for fragmentation, but fill certain fields as they should appear in the fragment:
- **ipv4**: `ip.ip_len` must be calculated as it should appear in the fragment.
The C code uses `ip.ip_len` to determine the size of the fragmented portion.
@@ -2327,6 +2333,7 @@ Returns an array of information about all subsequent, pending instances in the c
| range | table | effective range of [counters](#in-profile-filters) `--in-range` or `--out-range` depending on the current direction |
| payload | table | effective payload filter : payload name indexed table. |
| payload_filter | string | effective payload filter : a comma-separated list of payload names. |
| arg | table | instance arguments |
**range**
@@ -3562,10 +3569,10 @@ Retrieves, removes, and returns the first element of the [execution plan](#execu
### plan_clear
```
function plan_clear(desync)
function plan_clear(desync, max)
```
Clears the [execution plan](#execution_plan) in `desync.plan` by removing all `instance` elements.
Clears up to the "max" instances if "max" is defined or the whole [execution plan](#execution_plan) in `desync.plan`.
### orchestrate
@@ -3579,10 +3586,10 @@ If `ctx=nil`, it does nothing, assuming the plan is already in `desync.plan`.
### replay_execution_plan
```
function replay_execution_plan(desync)
function replay_execution_plan(desync, max)
```
Executes the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
Executes up to the "max" instances if "max" is defined, or the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
# zapret-antidpi.lua DPI attack program library
@@ -4380,13 +4387,26 @@ function condition(ctx, desync)
- arg: `iff` - name of the [iff function](#iff-functions)
- arg: `neg` - invert the `iff` value; defaults to `false`
- arg: `instances` - how many following instances to execute conditionally. all if not defined.
`condition` calls `iff`. If `iff xor neg = true`, all instances in the `plan` are executed; otherwise, the plan is cleared.
### per_instance_condition
```
function per_instance_condition(ctx, desync)
```
- arg: `instances` - how many following instances to execute conditionally. all if not defined.
All following instanced are called only if they have "cond" argument with the "iff" function name and it returns true. The "cond_neg" argument inverts "cond" result.
Names are not iff/neg to avoid conflict with other orchestrators.
### stopif
```
function condition(ctx, desync)
function stopif(ctx, desync)
```
- arg: `iff` - name of the [iff function](#iff-functions)
@@ -4438,6 +4458,22 @@ function cond_payload_str(desync)
Returns `true` if the substring `pattern` is present in `desync.dis.payload`.
This is a basic signature detector. If the C code does not recognize the protocol you need, you can write your own signature detector and run subsequent instances under a `condition` orchestrator using your detector as the `iff` function.
#### cond_tcp_has_ts
```
function cond_tcp_ts(desync)
```
Returns `true` if the dissect is tcp and has tcp timestamp option.
#### cond_lua
```
function cond_lua(desync)
```
Executes a Lua code from the "code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
# Auxiliary programs

View File

@@ -56,21 +56,21 @@
- [Генерация случайных данных](#генерация-случайных-данных)
- [brandom](#brandom)
- [Парсинг](#парсинг)
- [parse\_hex](#parse_hex)
- [parse_hex](#parse_hex)
- [Криптография](#криптография)
- [bcryptorandom](#bcryptorandom)
- [bxor,bor,band](#bxorborband)
- [hash](#hash)
- [aes](#aes)
- [aes\_gcm](#aes_gcm)
- [aes\_ctr](#aes_ctr)
- [aes_gcm](#aes_gcm)
- [aes_ctr](#aes_ctr)
- [hkdf](#hkdf)
- [Компрессия](#компрессия)
- [gunzip](#gunzip)
- [gzip](#gzip)
- [Системные функции](#системные-функции)
- [uname](#uname)
- [clock\_gettime](#clock_gettime)
- [clock_gettime](#clock_gettime)
- [getpid](#getpid)
- [stat](#stat)
- [time](#time)
@@ -79,23 +79,23 @@
- [standard rawsend](#standard-rawsend)
- [Диссекция и реконструкция](#диссекция-и-реконструкция)
- [dissect](#dissect)
- [reconstruct\_dissect](#reconstruct_dissect)
- [reconstruct\_hdr](#reconstruct_hdr)
- [csum\_fix](#csum_fix)
- [reconstruct_dissect](#reconstruct_dissect)
- [reconstruct_hdr](#reconstruct_hdr)
- [csum_fix](#csum_fix)
- [conntrack](#conntrack)
- [Получение ip адресов](#получение-ip-адресов)
- [Прием и отсылка пакетов](#прием-и-отсылка-пакетов)
- [rawsend](#rawsend)
- [raw\_packet](#raw_packet)
- [raw_packet](#raw_packet)
- [Работа с пейлоадами](#работа-с-пейлоадами)
- [маркеры](#маркеры)
- [resolve\_pos](#resolve_pos)
- [tls\_mod](#tls_mod)
- [resolve_pos](#resolve_pos)
- [tls_mod](#tls_mod)
- [Управление выполнением инстансов](#управление-выполнением-инстансов)
- [instance\_cutoff](#instance_cutoff)
- [lua\_cutoff](#lua_cutoff)
- [execution\_plan](#execution_plan)
- [execution\_plan\_cancel](#execution_plan_cancel)
- [instance_cutoff](#instance_cutoff)
- [lua_cutoff](#lua_cutoff)
- [execution_plan](#execution_plan)
- [execution_plan_cancel](#execution_plan_cancel)
- [Библиотека базовых функций zapret-lib.lua](#библиотека-базовых-функций-zapret-liblua)
- [Базовые desync функции](#базовые-desync-функции)
- [luaexec](#luaexec)
@@ -103,16 +103,16 @@
- [pktdebug](#pktdebug)
- [argdebug](#argdebug)
- [posdebug](#posdebug)
- [detect\_payload\_str](#detect_payload_str)
- [desync\_orchestrator\_example](#desync_orchestrator_example)
- [detect_payload_str](#detect_payload_str)
- [desync_orchestrator_example](#desync_orchestrator_example)
- [Служебные функции](#служебные-функции)
- [var\_debug](#var_debug)
- [var_debug](#var_debug)
- [deepcopy](#deepcopy)
- [logical\_xor](#logical_xor)
- [array\_search](#array_search)
- [logical_xor](#logical_xor)
- [array_search](#array_search)
- [Работа со строками](#работа-со-строками)
- [in\_list](#in_list)
- [find\_next\_line](#find_next_line)
- [in_list](#in_list)
- [find_next_line](#find_next_line)
- [Обслуживание raw string](#обслуживание-raw-string)
- [hex](#hex)
- [pattern](#pattern)
@@ -120,18 +120,18 @@
- [Обслуживание tcp sequence numbers](#обслуживание-tcp-sequence-numbers)
- [Обслуживание позиций](#обслуживание-позиций)
- [Диссекция](#диссекция)
- [dissect\_url](#dissect_url)
- [dissect\_nld](#dissect_nld)
- [dissect\_http](#dissect_http)
- [dissect\_tls](#dissect_tls)
- [dissect_url](#dissect_url)
- [dissect_nld](#dissect_nld)
- [dissect_http](#dissect_http)
- [dissect_tls](#dissect_tls)
- [Работа с элементами L3 и L4 протоколов](#работа-с-элементами-l3-и-l4-протоколов)
- [find\_tcp\_options](#find_tcp_options)
- [find_tcp_options](#find_tcp_options)
- [ip6hdr](#ip6hdr)
- [ip protocol](#ip-protocol)
- [packet\_len](#packet_len)
- [packet_len](#packet_len)
- [Работа с именами хостов](#работа-с-именами-хостов)
- [genhost](#genhost)
- [host\_ip](#host_ip)
- [host_ip](#host_ip)
- [Операции с именами файлов и путями](#операции-с-именами-файлов-и-путями)
- [Чтение и запись файлов](#чтение-и-запись-файлов)
- [Компрессия данных](#компрессия-данных)
@@ -140,29 +140,29 @@
- [standard ipid](#standard-ipid)
- [standard fooling](#standard-fooling)
- [standard ipfrag](#standard-ipfrag)
- [apply\_ip\_id](#apply_ip_id)
- [apply\_fooling](#apply_fooling)
- [apply_ip_id](#apply_ip_id)
- [apply_fooling](#apply_fooling)
- [ipfrag2](#ipfrag2)
- [wssize\_rewrite](#wssize_rewrite)
- [dis\_reverse](#dis_reverse)
- [wssize_rewrite](#wssize_rewrite)
- [dis_reverse](#dis_reverse)
- [IP адреса и интерфейсы](#ip-адреса-и-интерфейсы)
- [Отсылка](#отсылка)
- [rawsend\_dissect\_ipfrag](#rawsend_dissect_ipfrag)
- [rawsend\_dissect\_segmented](#rawsend_dissect_segmented)
- [rawsend\_payload\_segmented](#rawsend_payload_segmented)
- [rawsend_dissect_ipfrag](#rawsend_dissect_ipfrag)
- [rawsend_dissect_segmented](#rawsend_dissect_segmented)
- [rawsend_payload_segmented](#rawsend_payload_segmented)
- [Стандартные фильтры direction и payload](#стандартные-фильтры-direction-и-payload)
- [Работа с многопакетными пейлоадам](#работа-с-многопакетными-пейлоадам)
- [Оркестрация](#оркестрация)
- [instance\_cutoff\_shim](#instance_cutoff_shim)
- [cutoff\_shim\_check](#cutoff_shim_check)
- [apply\_arg\_prefix](#apply_arg_prefix)
- [apply\_execution\_plan](#apply_execution_plan)
- [verdict\_aggregate](#verdict_aggregate)
- [plan\_instance\_execute](#plan_instance_execute)
- [plan\_instance\_pop](#plan_instance_pop)
- [plan\_clear](#plan_clear)
- [instance_cutoff_shim](#instance_cutoff_shim)
- [cutoff_shim_check](#cutoff_shim_check)
- [apply_arg_prefix](#apply_arg_prefix)
- [apply_execution_plan](#apply_execution_plan)
- [verdict_aggregate](#verdict_aggregate)
- [plan_instance_execute](#plan_instance_execute)
- [plan_instance_pop](#plan_instance_pop)
- [plan_clear](#plan_clear)
- [orchestrate](#orchestrate)
- [replay\_execution\_plan](#replay_execution_plan)
- [replay_execution_plan](#replay_execution_plan)
- [Библиотека программ атаки на DPI zapret-antidpi.lua](#библиотека-программ-атаки-на-dpi-zapret-antidpilua)
- [Стандартные наборы параметров](#стандартные-наборы-параметров)
- [standard direction](#standard-direction)
@@ -172,22 +172,22 @@
- [send](#send)
- [pktmod](#pktmod)
- [Дурение http](#дурение-http)
- [http\_hostcase](#http_hostcase)
- [http\_domcase](#http_domcase)
- [http\_methodeol](#http_methodeol)
- [http\_unixeol](#http_unixeol)
- [http_hostcase](#http_hostcase)
- [http_domcase](#http_domcase)
- [http_methodeol](#http_methodeol)
- [http_unixeol](#http_unixeol)
- [Замена window size](#замена-window-size)
- [wsize](#wsize)
- [wssize](#wssize)
- [Фейки](#фейки)
- [syndata](#syndata)
- [tls\_client\_hello\_clone](#tls_client_hello_clone)
- [tls_client_hello_clone](#tls_client_hello_clone)
- [fake](#fake)
- [rst](#rst)
- [TCP сегментация](#tcp-сегментация)
- [multisplit](#multisplit)
- [multidisorder](#multidisorder)
- [multidisorder\_legacy](#multidisorder_legacy)
- [multidisorder_legacy](#multidisorder_legacy)
- [fakedsplit](#fakedsplit)
- [fakeddisorder](#fakeddisorder)
- [hostfakesplit](#hostfakesplit)
@@ -195,32 +195,35 @@
- [oob](#oob)
- [Дурение udp](#дурение-udp)
- [udplen](#udplen)
- [dht\_dn](#dht_dn)
- [dht_dn](#dht_dn)
- [Другие функции](#другие-функции)
- [synack](#synack)
- [synack\_split](#synack_split)
- [synack_split](#synack_split)
- [Библиотека программ автоматизации и оркестрации zapret-auto.lua](#библиотека-программ-автоматизации-и-оркестрации-zapret-autolua)
- [Хранилище состояний](#хранилище-состояний)
- [automate\_conn\_record](#automate_conn_record)
- [standard\_hostkey](#standard_hostkey)
- [automate\_host\_record](#automate_host_record)
- [automate_conn_record](#automate_conn_record)
- [standard_hostkey](#standard_hostkey)
- [automate_host_record](#automate_host_record)
- [Обслуживание удач и неудач](#обслуживание-удач-и-неудач)
- [automate\_failure\_counter](#automate_failure_counter)
- [automate\_failure\_counter\_reset](#automate_failure_counter_reset)
- [automate_failure_counter](#automate_failure_counter)
- [automate_failure_counter_reset](#automate_failure_counter_reset)
- [Детекция удач и неудач](#детекция-удач-и-неудач)
- [automate\_failure\_check](#automate_failure_check)
- [standard\_success\_detector](#standard_success_detector)
- [standard\_failure\_detector](#standard_failure_detector)
- [automate_failure_check](#automate_failure_check)
- [standard_success_detector](#standard_success_detector)
- [standard_failure_detector](#standard_failure_detector)
- [Оркестраторы](#оркестраторы)
- [circular](#circular)
- [repeater](#repeater)
- [condition](#condition)
- [per_instance_condition](#per_instance_condition)
- [stopif](#stopif)
- [iff функции](#iff-функции)
- [cond\_true](#cond_true)
- [cond\_false](#cond_false)
- [cond\_random](#cond_random)
- [cond\_payload\_str](#cond_payload_str)
- [cond_true](#cond_true)
- [cond_false](#cond_false)
- [cond_random](#cond_random)
- [cond_payload_str](#cond_payload_str)
- [cond_tcp_has_ts](#cond_tcp_has_ts)
- [cond_lua](#cond_lua)
- [Вспомогательные программы](#вспомогательные-программы)
- [ip2net](#ip2net)
- [mdig](#mdig)
@@ -244,16 +247,16 @@
- [Система ведения листов](#система-ведения-листов)
- [Стандартные файлы листов](#стандартные-файлы-листов)
- [Скрипты ipset](#скрипты-ipset)
- [clear\_lists.sh](#clear_listssh)
- [create\_ipset.sh](#create_ipsetsh)
- [get\_config.sh](#get_configsh)
- [get\_user.sh](#get_usersh)
- [get\_ipban.sh](#get_ipbansh)
- [get\_exclude.sh](#get_excludesh)
- [get\_antifilter\_\*.sh](#get_antifilter_sh)
- [get\_antizapret\_domains.sh](#get_antizapret_domainssh)
- [get\_refilter\_\*.sh](#get_refilter_sh)
- [get\_reestr\_\*.sh](#get_reestr_sh)
- [clear_lists.sh](#clear_listssh)
- [create_ipset.sh](#create_ipsetsh)
- [get_config.sh](#get_configsh)
- [get_user.sh](#get_usersh)
- [get_ipban.sh](#get_ipbansh)
- [get_exclude.sh](#get_excludesh)
- [get_antifilter_*.sh](#get_antifilter_sh)
- [get_antizapret_domains.sh](#get_antizapret_domainssh)
- [get_refilter_*.sh](#get_refilter_sh)
- [get_reestr_*.sh](#get_reestr_sh)
- [Система ipban](#система-ipban)
- [Стартовые скрипты](#стартовые-скрипты)
- [Интеграция с firewall](#интеграция-с-firewall)
@@ -1530,6 +1533,7 @@ ipv6 extension headers и tcp options представляются в форме
| :------------ | :----- | :--------------------------------------------------------------- |
| ip | table | заголовок ipv4 |
| ip6 | table | заголовок ipv6 |
| frag_off | number | смещение IP фрагмента. присутствует только в IP фрагментах. |
| tcp | table | заголовок tcp |
| udp | table | заголовок udp |
| icmp | table | заголовок icmp |
@@ -2246,10 +2250,12 @@ function dissect(raw_ip)
function reconstruct_dissect(dissect[, reconstruct_opts])
```
Возвращает raw_ip. Все чексуммы считаются автоматически. L4 чексуммы портятся, если задан badsum в reconstruct_opts.
Возвращает raw_ip. Все чексуммы считаются автоматически. L4 чексуммы портятся, если задан badsum в [reconstruct_opts](#standard-reconstruct).
Реконструкция диссектов с IP фрагментацией происходит особым образом - с участием как Lua, так и C кода.
Lua код должен подготовить диссект полного пакета, подлежащего фрагментации, но заполнить некоторые поля такими, какими они должны быть во фрагменте.
Реконструкция диссектов с IP фрагментацией происходит особым образом. Есть 2 варианта.
1. Если присутствует поле "frag_off", tcp/udp/icmp хедеры игнорируются, payload содержит raw ip payload. В таком виде приходят диссекты фрагментированных IP пакетов. nfqws2 не выполняет дефрагментацию на IP уровне. Но это очень настойчиво делают Linux системы - чтобы пришел фрагмент в nfqws2 надо сильно постараться, вставив в prerouting или output "notrack". Диссекты в таком виде могут быть реконструированы как есть. Но готовить их в Lua крайне неудобно, поскольку придется проходить через черную магию работы с бинарным представлением.
2. Если поле "frag_off" отсутствует, реконструкция фрагментов выполняется из диссекта целого пакета с участием как Lua, так и C кода. Lua код должен подготовить диссект полного пакета, подлежащего фрагментации, но заполнить некоторые поля такими, какими они должны быть во фрагменте.
- ipv4 : ip.ip_len должен быть рассчитан таким, каким он должен быть во фрагменте.
По ip.ip_len С код определяет размер фрагментированной части.
@@ -2481,6 +2487,7 @@ function execution_plan(ctx)
| range | table | эффективный диапазон [счетчиков](#внутрипрофильные-фильтры) `--in-range` или `--out-range` в зависимости от текущего направления |
| payload | table | эффективный фильтр payload . таблица с индексами - названиями типа пейлоада |
| payload_filter | string | эффективный фильтр payload . список названий пейлоадов через запятую (иное представление payload) |
| arg | table | аргументы инстанса |
**range**
@@ -3741,10 +3748,10 @@ function plan_instance_pop(desync)
### plan_clear
```
function plan_clear(desync)
function plan_clear(desync, max)
```
Очищает [execution plan](#execution_plan) в desync.plan - удаляет все `instance`.
Очищает первые max инстансов, если max задан, либо весь [execution plan](#execution_plan) в desync.plan.
### orchestrate
@@ -3758,10 +3765,10 @@ function orchestrate(ctx, desync)
### replay_execution_plan
```
function replay_execution_plan(desync)
function replay_execution_plan(desync, max)
```
Выполняет весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
Выполняет max инстансов, если max задан, либо весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
# Библиотека программ атаки на DPI zapret-antidpi.lua
@@ -4560,13 +4567,25 @@ function condition(ctx, desync)
- arg: iff - имя [функции условия](#iff-функции)
- arg: neg - инвертировать значение iff. по умолчанию - false
- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано.
condition вызывает iff. если iff xor neg = true, выполняются все инстансы plan, иначе план очищается.
### per_instance_condition
```
function per_instance_condition(ctx, desync)
```
- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано.
Все последующие инстансы вызываются только, если у них есть аргумент "cond", содержащий iff функцию, и она возвращает true. Аргумент "cond_neg" инвертирует ее значение.
Имена аргументов не iff/neg, чтобы исключить конфликт с другими оркестраторами.
### stopif
```
function condition(ctx, desync)
function stopif(ctx, desync)
```
- arg: iff - имя [функции условия](#iff-функции)
@@ -4618,6 +4637,22 @@ function cond_payload_str(desync)
Возвращает true, если в desync.dis.payload присутствует подстрока pattern.
Это простейший сигнатурый детектор. Если C код не распознает нужный вам протокол, вы можете написать свой сигнатурный детектор и запускать последующие инстансы под оркестратором condition с вашим детектором в качестве iff.
#### cond_tcp_has_ts
```
function cond_tcp_ts(desync)
```
Возвращает true, если диссект является tcp и присутствует timestamp tcp option.
#### cond_lua
```
function cond_lua(desync)
```
Выполняет Lua код из аргумента "code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
# Вспомогательные программы
## ip2net

View File

@@ -54,7 +54,7 @@ standard rawsend :
standard payload :
* payload - comma separarated list of allowed payload types. if not present - allow non-empty known payloads.
* payload - comma separated list of allowed payload types. if not present - allow non-empty known payloads.
standard ip_id :

View File

@@ -405,6 +405,34 @@ function cond_payload_str(desync)
end
return desync.dis.payload and string.find(desync.dis.payload,desync.arg.pattern,1,true)
end
-- true if dissect is tcp and timestamp tcp option is present
function cond_tcp_has_ts(desync)
return desync.dis.tcp and find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
end
-- exec lua code in "code" arg and return it's result
function cond_lua(desync)
if not desync.arg.code then
error("cond_lua: no 'code' parameter")
end
local fname = desync.func_instance.."_cond_code"
if not _G[fname] then
local err
_G[fname], err = load(desync.arg.code, fname)
if not _G[fname] then
error(err)
return
end
end
-- allow dynamic code to access desync
_G.desync = desync
local res, v = pcall(_G[fname])
_G.desync = nil
if not res then
error(v);
end
return v
end
-- check iff function available. error if not
function require_iff(desync, name)
if not desync.arg.iff then
@@ -418,18 +446,55 @@ end
-- for example, this can be used by custom protocol detectors
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
-- arg: neg - invert condition function result
-- arg: instances - how many instances execute conditionally. all if not defined
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
function condition(ctx, desync)
require_iff(desync, "condition")
orchestrate(ctx, desync)
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
DLOG("condition: true")
return replay_execution_plan(desync)
else
DLOG("condition: false")
plan_clear(desync)
plan_clear(desync, tonumber(desync.arg.instances))
if #desync.plan>0 then
DLOG("condition: executing remaining "..#desync.plan.." instance(s)")
end
end
return replay_execution_plan(desync)
end
-- execute further desync instances.
-- each instance may have "cond" and "cond_neg" args.
-- "cond" - condition function. "neg" - invert condition function result
-- arg: instances - how many instances execute conditionally. all if not defined
function per_instance_condition(ctx, desync)
orchestrate(ctx, desync)
local verdict = VERDICT_PASS
local n = 0
local max = tonumber(desync.arg.instances)
while not max or n<max do
local instance = plan_instance_pop(desync)
if not instance then break end
if instance.arg.cond then
if type(_G[instance.arg.cond])~="function" then
error(name..": invalid 'iff' function '"..instance.arg.cond.."'")
end
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
verdict = plan_instance_execute(desync, verdict, instance)
else
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
end
else
DLOG("per_instance_condition: no 'cond' arg in '"..instance.func_instance.."'. skipping")
end
n = n + 1
end
if #desync.plan>0 then
DLOG("per_instance_condition: executing remaining "..#desync.plan.." instance(s) unconditionally")
end
return verdict_aggregate(verdict, replay_execution_plan(desync))
end
-- clear execution plan if user provided 'iff' functions returns true
-- can be used with other orchestrators to stop execution conditionally
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)

View File

@@ -29,8 +29,11 @@ function luaexec(ctx, desync)
end
-- allow dynamic code to access desync
_G.desync = desync
_G[fname]()
local res, err = pcall(_G[fname])
_G.desync = nil
if not res then
error(err);
end
end
-- basic desync function
@@ -206,8 +209,13 @@ end
function plan_instance_pop(desync)
return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil
end
function plan_clear(desync)
while table.remove(desync.plan) do end
function plan_clear(desync, max)
if max then
local n=0
while n<max and table.remove(desync.plan,1) do n=n+1 end
else
while table.remove(desync.plan) do end
end
end
-- this approach allows nested orchestrators
function orchestrate(ctx, desync)
@@ -230,12 +238,17 @@ function desync_copy(desync)
return dcopy
end
-- redo what whould be done without orchestration
function replay_execution_plan(desync)
function replay_execution_plan(desync, max)
local verdict = VERDICT_PASS
while true do
local n=0
while not max or n<max do
local instance = plan_instance_pop(desync)
if not instance then break end
verdict = plan_instance_execute(desync, verdict, instance)
n = n + 1
end
if max and n>=max then
DLOG("replay_execution_plan: reached max instances limit "..max)
end
return verdict
end
@@ -321,22 +334,24 @@ end
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
function barray(a, packer)
local sa={}
if a then
local s=""
for i=1,#a do
s = s .. packer(a[i])
sa[i] = packer(a[i])
end
return s
return table.concat(sa)
end
end
-- convert table a to packed string using 'packer' function. any indexes, any order
function btable(a, packer)
local sa={}
if a then
local s=""
for k,v in pairs(a) do
s = s .. packer(v)
sa[k] = packer(v)
end
return s
return table.concat(sa)
end
end
@@ -932,11 +947,11 @@ function apply_fooling(desync, dis, fooling_options)
local bin
if fooling_options.ip6_hopbyhop then
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
end
if fooling_options.ip6_hopbyhop2 then
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
end
-- for possible unfragmentable part
if fooling_options.ip6_destopt then
@@ -1094,7 +1109,7 @@ end
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
function rawsend_dissect_ipfrag(dis, options)
if options and options.ipfrag and options.ipfrag.ipfrag then
if options and options.ipfrag and options.ipfrag.ipfrag and not dis.frag then
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
if type(_G[frag_func]) ~= "function" then
error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist")

View File

@@ -82,13 +82,13 @@ end
-- test case :
-- endpoint1:
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{5001}" queue num 200 bypass
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport "{5001}" queue num 200 bypass
-- iperf -i 1 -c endpoint2
-- endpoint2:
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD --server
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD --server
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp sport "{5001}" queue num 200 bypass
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport "{5001}" queue num 200 bypass

View File

@@ -420,26 +420,35 @@ function test_time(...)
local unixtime=os.time()
local tm = localtime(unixtime);
local t
print()
print("now: "..tm.str.." "..tm.zone.." = "..unixtime)
local tm = gmtime(unixtime);
print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime)
print()
for i=1,20 do
unixtime = math.random(0,10000000000);
unixtime = math.random(0,0x7FFFFFFF);
tm = localtime(unixtime);
local t = timelocal(tm)
t = timelocal(tm)
print("timelocal: "..tm.str.." "..tm.zone.." = "..t)
print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" )
test_assert(t==unixtime)
unixtime = math.random(0,10000000000);
unixtime = math.random(0,0x7FFFFFFF);
tm = gmtime(unixtime);
t = timegm(tm)
print("timegm: "..tm.str.." "..tm.zone.." = "..t)
print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" )
test_assert(t==unixtime)
end
unixtime = math.random(0x80000000,0xFFFFFFFF);
tm = gmtime(unixtime)
t = timegm(tm)
print( t==unixtime and "TIME 0x80000000..0xFFFFFFFF OK" or "TIME 0x80000000..0xFFFFFFFF FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
unixtime = math.random(0x100000000,0x200000000);
tm = gmtime(unixtime)
t = timegm(tm)
print( t==unixtime and "TIME 64 OK" or "TIME 64 FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
end
function test_gzip()

View File

@@ -19,10 +19,10 @@ struct icmp46
uint16_t icmp_cksum;
union
{
uint32_t icmp_data32;
uint16_t icmp_data16[2];
uint8_t icmp_data8[4];
};
uint32_t data32;
uint16_t data16[2];
uint8_t data8[4];
} data;
};
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);

View File

@@ -353,7 +353,7 @@ void ConntrackPoolDump(const t_conntrack *p)
HASH_ITER(hh, p->pool, t, tmp) {
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%llu ",
proto_name(t->conn.l4proto),
sa1, t->conn.sport, sa2, t->conn.dport,
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",

View File

@@ -64,12 +64,12 @@
* Add "length" to the length.
* Set Corrupted when overflow has occurred.
*/
static uint32_t addTemp;
#define SHA224_256AddLength(context, length) \
(addTemp = (context)->Length_Low, (context)->Corrupted = \
(((context)->Length_Low += (length)) < addTemp) && \
(++(context)->Length_High == 0) ? shaInputTooLong : \
(context)->Corrupted )
static int SHA224_256AddLength(SHA256Context *context, uint32_t length)
{
uint32_t addTemp = context->Length_Low;
if (((context->Length_Low += length) < addTemp) && (++(context)->Length_High == 0)) context->Corrupted = shaInputTooLong;
return context->Corrupted;
}
/* Local Function Prototypes */
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);

View File

@@ -358,9 +358,9 @@ void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp)
char stype[32];
str_icmp_type_name(stype,sizeof(stype),v6,icmp->icmp_type);
if (icmp->icmp_type==ICMP_ECHO || icmp->icmp_type==ICMP_ECHOREPLY || icmp->icmp_type==ICMP6_ECHO_REQUEST || icmp->icmp_type==ICMP6_ECHO_REPLY)
snprintf(s,s_len,"icmp_type=%s icmp_code=%u id=0x%04X seq=%u",stype,icmp->icmp_code,ntohs(icmp->icmp_data16[0]),ntohs(icmp->icmp_data16[1]));
snprintf(s,s_len,"icmp_type=%s icmp_code=%u id=0x%04X seq=%u",stype,icmp->icmp_code,ntohs(icmp->data.data16[0]),ntohs(icmp->data.data16[1]));
else
snprintf(s,s_len,"icmp_type=%s icmp_code=%u data=0x%08X",stype,icmp->icmp_code,ntohl(icmp->icmp_data32));
snprintf(s,s_len,"icmp_type=%s icmp_code=%u data=0x%08X",stype,icmp->icmp_code,ntohl(icmp->data.data32));
}
void print_icmphdr(const struct icmp46 *icmp, bool v6)
{
@@ -383,9 +383,11 @@ bool proto_check_ipv4_payload(const uint8_t *data, size_t len)
return len >= ntohs(((struct ip*)data)->ip_len);
}
// move to transport protocol
void proto_skip_ipv4(const uint8_t **data, size_t *len)
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off)
{
uint8_t off = ((struct ip*)*data)->ip_hl << 2;
if (frag_off) *frag_off = (ntohs(((struct ip*)*data)->ip_off) & IP_OFFMASK) << 3;
if (frag) *frag = ntohs(((struct ip*)*data)->ip_off) & (IP_OFFMASK|IP_MF);
*data += off;
*len -= off;
}
@@ -434,21 +436,25 @@ bool proto_check_ipv6_payload(const uint8_t *data, size_t len)
}
// move to transport protocol
// proto_type = 0 => error
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off)
{
size_t hdrlen;
uint8_t HeaderType;
uint16_t plen;
struct ip6_hdr *ip6 = (struct ip6_hdr*)*data;
uint16_t plen;
uint16_t fr_off=0;
bool fr=false;
uint8_t HeaderType;
if (proto_type) *proto_type = 0; // put error in advance
if (frag) *frag = false;
if (frag_off) *frag_off = 0;
HeaderType = ip6->ip6_nxt;
if (proto_type) *proto_type = HeaderType;
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
*data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header
if (plen < *len) *len = plen;
while (*len) // need at least one byte for NextHeader field
while (*len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
{
switch (HeaderType)
{
@@ -463,6 +469,11 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
break;
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8;
if (*len < hdrlen) return; // error
fr_off = ntohs(((struct ip6_frag*)*data)->ip6f_offlg & IP6F_OFF_MASK);
fr = ((struct ip6_frag*)*data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
if (frag_off) *frag_off = fr_off;
if (frag) *frag = fr;
break;
case IPPROTO_AH:
// special case. length in ah header is in 32-bit words minus 2
@@ -488,8 +499,10 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
{
size_t hdrlen;
uint8_t HeaderType, last_proto, *data;
uint16_t plen;
uint8_t HeaderType, last_proto, *data;
bool fr=false;
uint16_t fr_off=0;
if (len<sizeof(struct ip6_hdr)) return false;
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
@@ -497,7 +510,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
data = (uint8_t*)(ip6+1);
len -= sizeof(struct ip6_hdr);
if (plen < len) len = plen;
while (len) // need at least one byte for NextHeader field
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
{
if (last_proto==proto) return data; // found
switch (last_proto)
@@ -513,6 +526,9 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
break;
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8;
if (len < hdrlen) return false; // error
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
break;
case IPPROTO_AH:
// special case. length in ah header is in 32-bit words minus 2
@@ -546,14 +562,14 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
dis->ip = (const struct ip *) data;
dis->proto = dis->ip->ip_p;
p = data;
proto_skip_ipv4(&data, &len);
proto_skip_ipv4(&data, &len, &dis->frag, &dis->frag_off);
dis->len_l3 = data-p;
}
else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len)))
{
dis->ip6 = (const struct ip6_hdr *) data;
p = data;
proto_skip_ipv6(&data, &len, &dis->proto);
proto_skip_ipv6(&data, &len, &dis->proto, &dis->frag, &dis->frag_off);
dis->len_l3 = data-p;
}
else
@@ -562,31 +578,31 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
}
dis->transport_len = len;
dis->len_l4 = 0;
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
if (!dis->frag)
{
dis->tcp = (const struct tcphdr *) data;
p = data;
proto_skip_tcp(&data, &len);
dis->len_l4 = data-p;
}
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
{
dis->udp = (const struct udphdr *) data;
p = data;
proto_skip_udp(&data, &len);
dis->len_l4 = data-p;
}
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
{
dis->icmp = (const struct icmp46 *) data;
p = data;
proto_skip_icmp(&data, &len);
dis->len_l4 = data-p;
}
else
{
dis->len_l4 = 0;
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
{
dis->tcp = (const struct tcphdr *) data;
p = data;
proto_skip_tcp(&data, &len);
dis->len_l4 = data-p;
}
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
{
dis->udp = (const struct udphdr *) data;
p = data;
proto_skip_udp(&data, &len);
dis->len_l4 = data-p;
}
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
{
dis->icmp = (const struct icmp46 *) data;
p = data;
proto_skip_icmp(&data, &len);
dis->len_l4 = data-p;
}
}
dis->data_payload = data;
@@ -1753,6 +1769,7 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
{
struct sockaddr_storage sa;
socklen_t slen;
ssize_t wr;
#ifdef __FreeBSD__
// since FreeBSD 14 it requires hardcoded ipv4 values, although can also send ipv6 frames
@@ -1774,7 +1791,16 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
#endif
memset(&sa,0,slen);
sa.ss_family = family;
return sendto(sock, buf, len, 0, (struct sockaddr*)&sa, slen);
while ((wr=sendto(sock, buf, len, 0, (struct sockaddr*)&sa, slen))<0 && errno==EINTR);
if (wr<0)
{
char s[64];
snprintf(s,sizeof(s),"rawsend_sendto_divert: sendto (%zu)",len);
DLOG_PERROR(s);
return false;
}
return wr;
}
#endif
@@ -1906,47 +1932,32 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
#else
#ifdef __linux__
struct sockaddr_storage sa_src;
switch(dst->sa_family)
{
case AF_INET:
if (!b_bind_fix4) goto nofix;
extract_endpoints(data,NULL,NULL,NULL, &sa_src, NULL);
break;
case AF_INET6:
if (!b_bind_fix6) goto nofix;
extract_endpoints(NULL,data,NULL,NULL, &sa_src, NULL);
break;
default:
return false; // should not happen
}
//printf("family %u dev %s bind : ", dst->sa_family, ifout); print_sockaddr((struct sockaddr *)&sa_src); printf("\n");
// force outgoing interface for raw packets. linux may choose it wrong if ip rules exist
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifout, ifout ? strlen(ifout)+1 : 0) == -1)
{
DLOG_PERROR("rawsend: setsockopt(SO_BINDTODEVICE)");
return false;
}
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
{
DLOG_PERROR("rawsend: bind (ignoring)");
// do not fail. this can happen regardless of IP_FREEBIND
// rebind to any address
memset(&sa_src,0,sizeof(sa_src));
sa_src.ss_family = dst->sa_family;
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
{
DLOG_PERROR("rawsend: bind to any");
return false;
}
}
nofix:
#endif
// normal raw socket sendto
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
if (bytes==-1)
while ((bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen))<0 && errno==EINTR);
if (bytes<0)
{
char s[40];
char s[64];
snprintf(s,sizeof(s),"rawsend: sendto (%zu)",len);
DLOG_PERROR(s);
return false;

View File

@@ -175,10 +175,10 @@ void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
bool proto_check_ipv4(const uint8_t *data, size_t len);
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
void proto_skip_ipv4(const uint8_t **data, size_t *len);
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off);
bool proto_check_ipv6(const uint8_t *data, size_t len);
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type);
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off);
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
bool proto_check_tcp(const uint8_t *data, size_t len);
void proto_skip_tcp(const uint8_t **data, size_t *len);
@@ -203,6 +203,8 @@ struct dissect
size_t transport_len;
const uint8_t *data_payload;
size_t len_payload;
bool frag;
uint16_t frag_off;
};
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);

View File

@@ -188,7 +188,10 @@ static void packet_debug(bool replay, const struct dissect *dis)
{
char s_proto[16];
str_proto_name(s_proto,sizeof(s_proto),dis->proto);
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
if (dis->frag)
DLOG("\nIP FRAG off=%u PROTO %s: len=%zu : ", dis->frag_off, s_proto, dis->len_payload);
else
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
DLOG("\n");
}
@@ -2099,36 +2102,27 @@ static uint8_t dpi_desync_packet_play(
if (!!dis.ip != !!dis.ip6)
{
packet_debug(!!replay_piece_count, &dis);
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
// modified means we have already fixed the checksum or made it invalid intentionally
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
switch (dis.proto)
if (dis.tcp)
{
case IPPROTO_TCP:
if (dis.tcp)
{
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
}
break;
case IPPROTO_UDP:
if (dis.udp)
{
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
}
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
if (dis.icmp)
{
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
}
break;
default:
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
}
else if (dis.udp)
{
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
}
else if (dis.icmp)
{
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
}
else
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
}
else
DLOG("invalid packet - neither ipv4 or ipv6\n");

View File

@@ -165,7 +165,7 @@ void expand_bits(void *target, const void *source, unsigned int source_bitlen, u
unsigned int bitlen = target_bitlen<source_bitlen ? target_bitlen : source_bitlen;
unsigned int bytelen = bitlen>>3;
if ((target_bytelen-bytelen)>=1) memset(target+bytelen,0,target_bytelen-bytelen);
if ((target_bytelen-bytelen)>=1) memset((uint8_t*)target+bytelen,0,target_bytelen-bytelen);
memcpy(target,source,bytelen);
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8-bitlen)) - 1));
}
@@ -504,6 +504,14 @@ int getentropy(void *buf, size_t len)
}
#endif
ssize_t read_intr(int fd, void *buf, size_t count)
{
ssize_t rd;
while ((rd=read(fd,buf,count))<0 && errno==EINTR);
return rd;
}
bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
{
ssize_t rd;
@@ -526,7 +534,7 @@ bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
{
do
{
if ((rd=read(fd,p,sz))>0)
if ((rd=read_intr(fd,p,sz))>0)
{
p+=rd; sz-=rd;
}
@@ -537,7 +545,7 @@ bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
{
do
{
if ((rd=read(fd,p,sz))>0)
if ((rd=read_intr(fd,p,sz))>0)
{
p+=rd; sz-=rd;
}

View File

@@ -33,6 +33,8 @@ const char *strncasestr(const char *s,const char *find, size_t slen);
// [a-zA-z][a-zA-Z0-9]*
bool is_identifier(const char *p);
ssize_t read_intr(int fd, void *buf, size_t count);
bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size);
bool save_file(const char *filename, const void *buffer, size_t buffer_size);
bool append_to_list_file(const char *filename, const char *s);
@@ -114,7 +116,7 @@ const struct in6_addr *mask_from_bitcount6(uint32_t zct);
#elif defined(CLOCK_UPTIME)
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
#else
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTINIC
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTONIC
#endif
time_t boottime(void);

View File

@@ -1422,7 +1422,7 @@ void lua_push_icmphdr(lua_State *L, const struct icmp46 *icmp, size_t len)
lua_pushf_int(L,"icmp_type",icmp->icmp_type);
lua_pushf_int(L,"icmp_code",icmp->icmp_code);
lua_pushf_int(L,"icmp_cksum",ntohs(icmp->icmp_cksum));
lua_pushf_lint(L,"icmp_data",ntohl(icmp->icmp_data32));
lua_pushf_lint(L,"icmp_data",ntohl(icmp->data.data32));
}
else
lua_pushnil(L);
@@ -1508,9 +1508,11 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
// assume ipv6 packet structure was already checked for validity
size_t hdrlen;
lua_Integer idx = 1;
uint8_t HeaderType, *data;
uint16_t plen;
lua_Integer idx = 1;
uint16_t fr_off=0;
bool fr=false;
lua_pushliteral(L, "exthdr");
lua_newtable(L);
@@ -1521,7 +1523,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
len-=sizeof(struct ip6_hdr);
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
if (plen < len) len = plen;
while (len > 0) // need at least one byte for NextHeader field
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
{
switch (HeaderType)
{
@@ -1536,6 +1538,9 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
break;
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8;
if (len < hdrlen) goto end;
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
break;
case IPPROTO_AH:
// special case. length in ah header is in 32-bit words minus 2
@@ -1618,17 +1623,18 @@ void lua_push_dissect(lua_State *L, const struct dissect *dis)
if (dis)
{
lua_createtable(L, 0, 10);
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
lua_createtable(L, 0, 10+dis->frag);
lua_pushf_int(L,"l4proto",dis->proto);
lua_pushf_int(L,"transport_len",dis->transport_len);
lua_pushf_int(L,"l3_len",dis->len_l3);
lua_pushf_int(L,"l4_len",dis->len_l4);
lua_pushf_raw(L,"payload",dis->data_payload,dis->len_payload);
if (dis->frag) lua_pushf_int(L,"frag_off",dis->frag_off);
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
}
else
lua_pushnil(L);
@@ -2312,7 +2318,7 @@ bool lua_reconstruct_icmphdr(lua_State *L, int idx, struct icmp46 *icmp)
lua_getfield(L,idx,"icmp_data");
if (lua_type(L,-1)!=LUA_TNUMBER) goto err;
icmp->icmp_data32 = htonl((uint32_t)lua_tolint(L,-1));
icmp->data.data32 = htonl((uint32_t)lua_tolint(L,-1));
lua_pop(L, 1);
lua_getfield(L,idx,"icmp_cksum");
@@ -2383,11 +2389,24 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
struct udphdr *udp=NULL;
struct icmp46 *icmp=NULL;
const char *p;
bool frag;
LUA_STACK_GUARD_ENTER(L)
idx = lua_absindex(L, idx);
lua_getfield(L,idx,"frag_off");
if (lua_type(L,-1)!=LUA_TNIL)
{
luaL_checkinteger(L,-1); // verify type
frag = true;
}
else
frag = false;
lua_pop(L, 1);
if (frag) ip6_preserve_next = true; // there's no other source of next. no tcp, no udp, no icmp headers. just raw ip payload
lua_getfield(L,idx,"ip");
l = left;
if (lua_type(L,-1)==LUA_TTABLE)
@@ -2416,150 +2435,181 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
data+=l; left-=l;
lua_pop(L, 1);
lua_getfield(L,idx,"tcp");
l=0;
if (lua_type(L,-1)==LUA_TTABLE)
if (frag)
{
l = left;
tcp = (struct tcphdr*)data;
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
lua_getfield(L,idx,"payload");
p = lua_tolstring(L,-1,&lpayload);
if (p)
{
DLOG_ERR("reconstruct_dissect: bad tcp\n");
goto err;
if (lpayload>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: payload too large : %zu\n",lpayload);
goto err;
}
if (left<lpayload)
{
DLOG_ERR("reconstruct_dissect: payload does not fit into the buffer : payload %zu buffer_left %zu\n",lpayload,left);
goto err;
}
memcpy(data,p,lpayload);
data+=lpayload; left-=lpayload;
}
else
lpayload = 0;
lua_pop(L, 1);
l = data-buf;
}
else
{
lua_pop(L, 1);
lua_getfield(L,idx,"udp");
lua_getfield(L,idx,"tcp");
l=0;
if (lua_type(L,-1)==LUA_TTABLE)
{
l = sizeof(struct udphdr);
udp = (struct udphdr*)data;
if (!lua_reconstruct_udphdr(L, -1, udp))
l = left;
tcp = (struct tcphdr*)data;
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
{
DLOG_ERR("reconstruct_dissect: bad udp\n");
DLOG_ERR("reconstruct_dissect: bad tcp\n");
goto err;
}
}
else
{
lua_pop(L, 1);
lua_getfield(L,idx,"icmp");
lua_getfield(L,idx,"udp");
if (lua_type(L,-1)==LUA_TTABLE)
{
l = sizeof(struct icmp46);
icmp = (struct icmp46*)data;
if (!lua_reconstruct_icmphdr(L, -1, icmp))
l = sizeof(struct udphdr);
udp = (struct udphdr*)data;
if (!lua_reconstruct_udphdr(L, -1, udp))
{
DLOG_ERR("reconstruct_dissect: bad icmp\n");
DLOG_ERR("reconstruct_dissect: bad udp\n");
goto err;
}
}
}
}
data+=l; left-=l;
lua_pop(L, 1);
lua_getfield(L,idx,"payload");
p = lua_tolstring(L,-1,&lpayload);
if (p)
{
if (lpayload>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
goto err;
}
if (left<lpayload) goto err;
memcpy(data,p,lpayload);
data+=lpayload; left-=lpayload;
}
else
lpayload = 0;
lua_pop(L, 1);
l = data-buf;
if (!keepsum)
{
if (tcp)
{
tcp_fix_checksum(tcp,l-l3,ip,ip6);
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
}
else if (udp)
{
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
if (sz>0xFFFF)
else
{
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
lua_pop(L, 1);
lua_getfield(L,idx,"icmp");
if (lua_type(L,-1)==LUA_TTABLE)
{
l = sizeof(struct icmp46);
icmp = (struct icmp46*)data;
if (!lua_reconstruct_icmphdr(L, -1, icmp))
{
DLOG_ERR("reconstruct_dissect: bad icmp\n");
goto err;
}
}
}
}
data+=l; left-=l;
lua_pop(L, 1);
lua_getfield(L,idx,"payload");
p = lua_tolstring(L,-1,&lpayload);
if (p)
{
if (lpayload>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: payload too large : %zu\n",lpayload);
goto err;
}
udp->uh_ulen = htons((uint16_t)sz);
udp_fix_checksum(udp,l-l3,ip,ip6);
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
}
else if (icmp)
{
icmp_fix_checksum(icmp,l-l3,ip6);
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
}
}
if (ip)
{
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
{
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
uint16_t iplen = ntohs(ip->ip_len);
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
size_t frag_start = l3 + off;
if (iplen<l3 || iplen>l)
if (left<lpayload)
{
DLOG_ERR("ipv4 frag : invalid ip_len\n");
DLOG_ERR("reconstruct_dissect: payload does not fit into the buffer : payload %zu buffer_left %zu\n",lpayload,left);
goto err;
}
if (frag_start>l)
{
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
goto err;
}
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
l = iplen; // shrink packet to iplen
memcpy(data,p,lpayload);
data+=lpayload; left-=lpayload;
}
else
ip->ip_len = htons((uint16_t)l);
ip4_fix_checksum(ip);
}
else if (ip6)
{
// data points to reconstructed packet's end
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
if (frag)
{
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
uint8_t *endfrag = frag + 8;
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
lpayload = 0;
lua_pop(L, 1);
if (size_unfragmentable > plen)
l = data-buf;
if (!keepsum)
{
if (tcp)
{
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
goto err;
tcp_fix_checksum(tcp,l-l3,ip,ip6);
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
}
size_t size_fragmentable = plen - size_unfragmentable;
if ((endfrag + off + size_fragmentable) > data)
else if (udp)
{
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
goto err;
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
if (sz>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
goto err;
}
udp->uh_ulen = htons((uint16_t)sz);
udp_fix_checksum(udp,l-l3,ip,ip6);
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
}
else if (icmp)
{
icmp_fix_checksum(icmp,l-l3,ip6);
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
}
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
l = sizeof(struct ip6_hdr) + plen;
}
else
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
if (ip)
{
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
{
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
uint16_t iplen = ntohs(ip->ip_len);
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
size_t frag_start = l3 + off;
if (iplen<l3 || iplen>l)
{
DLOG_ERR("ipv4 frag : invalid ip_len\n");
goto err;
}
if (frag_start>l)
{
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
goto err;
}
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
l = iplen; // shrink packet to iplen
}
else
ip->ip_len = htons((uint16_t)l);
ip4_fix_checksum(ip);
}
else if (ip6)
{
// data points to reconstructed packet's end
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
if (frag)
{
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
uint8_t *endfrag = frag + 8;
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
if (size_unfragmentable > plen)
{
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
goto err;
}
size_t size_fragmentable = plen - size_unfragmentable;
if ((endfrag + off + size_fragmentable) > data)
{
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
goto err;
}
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
l = sizeof(struct ip6_hdr) + plen;
}
else
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
}
}
*len = l;
LUA_STACK_GUARD_LEAVE(L, 0)
return true;
@@ -3461,7 +3511,7 @@ static void *z_alloc(voidpf opaque, uInt items, uInt size)
}
static void z_free(voidpf opaque, voidpf address)
{
return free(address);
free(address);
}
static int luacall_gzip_init(lua_State *L)
{

View File

@@ -235,6 +235,7 @@ static int write_pidfile(FILE **Fpid)
#ifdef __linux__
// cookie must point to mod buffer with size RECONSTRUCT_MAX_SIZE
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
{
int id, ilen;
@@ -244,8 +245,8 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
uint32_t ifidx_out, ifidx_in;
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
size_t modlen;
uint8_t *mod = (uint8_t*)cookie;
uint32_t mark;
uint8_t mod[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
ph = nfq_get_msg_packet_hdr(nfa);
id = ph ? ntohl(ph->packet_id) : 0;
@@ -266,7 +267,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
if (ilen >= 0)
{
len = ilen;
modlen = sizeof(mod);
modlen = RECONSTRUCT_MAX_SIZE;
// there's no space to grow packet in recv blob from nfqueue. it can contain multiple packets with no extra buffer length for modifications.
// to support increased sizes use separate mod buffer
// this is not a problem because only LUA code can trigger VERDICT_MODIFY (and postnat workaround too, once a connection if first packet is dropped)
@@ -300,7 +301,7 @@ static void nfq_deinit(struct nfq_handle **h, struct nfq_q_handle **qh)
*h = NULL;
}
}
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh)
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *mod_buffer)
{
nfq_deinit(h, qh);
@@ -330,7 +331,7 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh)
}
DLOG_CONDUP("binding this socket to queue '%u'\n", params.qnum);
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, &params);
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, mod_buffer);
if (!*qh) {
DLOG_PERROR("nfq_create_queue()");
goto exiterr;
@@ -381,7 +382,7 @@ static int nfq_main(void)
int res, fd, e;
ssize_t rd;
FILE *Fpid = NULL;
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
uint8_t *buf=NULL, *mod=NULL;
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -423,7 +424,13 @@ static int nfq_main(void)
goto exok;
}
if (!nfq_init(&h, &qh))
if (!(buf = malloc(RECONSTRUCT_MAX_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE)))
{
DLOG_ERR("out of memory\n");
goto err;
}
if (!nfq_init(&h, &qh, mod))
goto err;
#ifdef HAS_FILTER_SSID
@@ -446,7 +453,7 @@ static int nfq_main(void)
fd = nfq_fd(h);
do
{
while ((rd = recv(fd, buf, sizeof(buf), 0)) >= 0)
while ((rd = recv(fd, buf, RECONSTRUCT_MAX_SIZE, 0)) >= 0)
{
if (bQuit) goto quit;
ReloadCheck();
@@ -482,6 +489,8 @@ static int nfq_main(void)
exok:
res=0;
ex:
free(mod);
free(buf);
nfq_deinit(&h, &qh);
lua_shutdown();
#ifdef HAS_FILTER_SSID
@@ -1649,7 +1658,7 @@ static void exithelp(void)
*all_protos=0;
for (t_l7proto pr=0 ; pr<L7_LAST; pr++)
{
if (pr) strncat(all_protos, " ", sizeof(all_protos)-1-1);
if (pr) strncat(all_protos, " ", sizeof(all_protos)-strlen(all_protos)-1);
strncat(all_protos, l7proto_str(pr), sizeof(all_protos)-strlen(all_protos)-1);
}
@@ -1722,7 +1731,7 @@ static void exithelp(void)
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n"
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
"\nMULTI-STRATEGY:\n"
" --new[=<name>]\t\t\t\t\t\t\t; begin new profile. optionally set name\n"
" --new[=<name>]\t\t\t\t\t\t; begin new profile. optionally set name\n"
" --skip\t\t\t\t\t\t\t; do not use this profile\n"
" --name=<name>\t\t\t\t\t\t; set profile name\n"
" --template[=<name>]\t\t\t\t\t; use this profile as template (must be named or will be useless)\n"

View File

@@ -17,12 +17,15 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
{
int i;
const uint8_t *p1,*p2;
if (level<1) return false;
for (i=1,p2=dom+dlen;i<level;i++)
{
for (p2--; p2>dom && *p2!='.'; p2--);
if (p2<=dom) return false;
}
for (p1=p2-1 ; p1>dom && *p1!='.'; p1--);
if (p1<dom) return false;
if (*p1=='.') p1++;
if (p) *p = p1;
if (len) *len = p2-p1;

View File

@@ -327,37 +327,57 @@ void daemonize(void)
int pid;
char cwd[PATH_MAX];
if (!getcwd(cwd, sizeof(cwd))) *cwd=0;
if (!getcwd(cwd, sizeof(cwd)))
{
DLOG_PERROR("getcwd");
*cwd=0;
}
pid = fork();
if (pid == -1)
{
DLOG_PERROR("fork");
exit(2);
exit(20);
}
else if (pid != 0)
exit(0);
if (*cwd)
{
int res = chdir(cwd);
}
if (*cwd && chdir(cwd)<0)
DLOG_PERROR("chdir");
if (setsid() == -1)
exit(2);
if (chdir("/") == -1)
exit(2);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
{
DLOG_PERROR("setsid");
exit(21);
}
if (close(STDIN_FILENO)<0 || close(STDOUT_FILENO)<0 || close(STDERR_FILENO)<0)
{
// will work only if debug not to console
DLOG_PERROR("close");
exit(22);
}
/* redirect fd's 0,1,2 to /dev/null */
open("/dev/null", O_RDWR);
int fd;
/* stdin */
fd = dup(0);
if (open("/dev/null", O_RDWR)<0)
{
// will work only if debug not to console
DLOG_PERROR("open(stdin)");
exit(23);
}
/* stdout */
fd = dup(0);
if (dup(0)<0)
{
// will work only if debug not to console
DLOG_PERROR("dup(stdout)");
exit(24);
}
/* stderror */
if (dup(0)<0)
{
// will work only if debug not to console
DLOG_PERROR("dup(stderr)");
exit(25);
}
}
bool writepid(const char *filename)