2024-01-25 12:01:53 +08:00
|
|
|
# Analyzers
|
|
|
|
|
|
|
|
Analyzers are one of the main components of OpenGFW. Their job is to analyze a connection, see if it's a protocol they
|
|
|
|
support, and if so, extract information from that connection and provide properties for the rule engine to match against
|
|
|
|
user-provided rules. OpenGFW will automatically analyze which analyzers are referenced in the given rules and enable
|
|
|
|
only those that are needed.
|
|
|
|
|
|
|
|
This document lists the properties provided by each analyzer that can be used by rules.
|
|
|
|
|
|
|
|
## DNS (TCP & UDP)
|
|
|
|
|
|
|
|
For queries:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"dns": {
|
|
|
|
"aa": false,
|
|
|
|
"id": 41953,
|
|
|
|
"opcode": 0,
|
|
|
|
"qr": false,
|
|
|
|
"questions": [
|
|
|
|
{
|
|
|
|
"class": 1,
|
|
|
|
"name": "www.google.com",
|
|
|
|
"type": 1
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"ra": false,
|
|
|
|
"rcode": 0,
|
|
|
|
"rd": true,
|
|
|
|
"tc": false,
|
|
|
|
"z": 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
For responses:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"dns": {
|
|
|
|
"aa": false,
|
|
|
|
"answers": [
|
|
|
|
{
|
|
|
|
"a": "142.251.32.36",
|
|
|
|
"class": 1,
|
|
|
|
"name": "www.google.com",
|
|
|
|
"ttl": 255,
|
|
|
|
"type": 1
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"id": 41953,
|
|
|
|
"opcode": 0,
|
|
|
|
"qr": true,
|
|
|
|
"questions": [
|
|
|
|
{
|
|
|
|
"class": 1,
|
|
|
|
"name": "www.google.com",
|
|
|
|
"type": 1
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"ra": true,
|
|
|
|
"rcode": 0,
|
|
|
|
"rd": true,
|
|
|
|
"tc": false,
|
|
|
|
"z": 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking DNS queries for `www.google.com`:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block Google DNS
|
|
|
|
action: drop
|
|
|
|
expr: dns != nil && !dns.qr && any(dns.questions, {.name == "www.google.com"})
|
|
|
|
```
|
|
|
|
|
|
|
|
## FET (Fully Encrypted Traffic)
|
|
|
|
|
|
|
|
Check https://www.usenix.org/system/files/usenixsecurity23-wu-mingshi.pdf for more information.
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"fet": {
|
|
|
|
"ex1": 3.7560976,
|
|
|
|
"ex2": true,
|
|
|
|
"ex3": 0.9512195,
|
|
|
|
"ex4": 39,
|
|
|
|
"ex5": false,
|
|
|
|
"yes": false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking fully encrypted traffic:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block suspicious proxy traffic
|
|
|
|
action: block
|
|
|
|
expr: fet != nil && fet.yes
|
|
|
|
```
|
|
|
|
|
|
|
|
## HTTP
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"http": {
|
|
|
|
"req": {
|
|
|
|
"headers": {
|
|
|
|
"accept": "*/*",
|
|
|
|
"host": "ipinfo.io",
|
|
|
|
"user-agent": "curl/7.81.0"
|
|
|
|
},
|
|
|
|
"method": "GET",
|
|
|
|
"path": "/",
|
|
|
|
"version": "HTTP/1.1"
|
|
|
|
},
|
|
|
|
"resp": {
|
|
|
|
"headers": {
|
|
|
|
"access-control-allow-origin": "*",
|
|
|
|
"content-length": "333",
|
|
|
|
"content-type": "application/json; charset=utf-8",
|
|
|
|
"date": "Wed, 24 Jan 2024 05:41:44 GMT",
|
|
|
|
"referrer-policy": "strict-origin-when-cross-origin",
|
|
|
|
"server": "nginx/1.24.0",
|
|
|
|
"strict-transport-security": "max-age=2592000; includeSubDomains",
|
|
|
|
"via": "1.1 google",
|
|
|
|
"x-content-type-options": "nosniff",
|
|
|
|
"x-envoy-upstream-service-time": "2",
|
|
|
|
"x-frame-options": "SAMEORIGIN",
|
|
|
|
"x-xss-protection": "1; mode=block"
|
|
|
|
},
|
|
|
|
"status": 200,
|
|
|
|
"version": "HTTP/1.1"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking HTTP requests to `ipinfo.io`:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block ipinfo.io HTTP
|
|
|
|
action: block
|
|
|
|
expr: http != nil && http.req != nil && http.req.headers != nil && http.req.headers.host == "ipinfo.io"
|
|
|
|
```
|
|
|
|
|
|
|
|
## SSH
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"ssh": {
|
|
|
|
"server": {
|
|
|
|
"comments": "Ubuntu-3ubuntu0.6",
|
|
|
|
"protocol": "2.0",
|
|
|
|
"software": "OpenSSH_8.9p1"
|
|
|
|
},
|
|
|
|
"client": {
|
|
|
|
"comments": "IMHACKER",
|
|
|
|
"protocol": "2.0",
|
|
|
|
"software": "OpenSSH_8.9p1"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking all SSH connections:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block SSH
|
|
|
|
action: block
|
|
|
|
expr: ssh != nil
|
|
|
|
```
|
|
|
|
|
|
|
|
## TLS
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"tls": {
|
|
|
|
"req": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"alpn": ["h2", "http/1.1"],
|
2024-01-25 12:01:53 +08:00
|
|
|
"ciphers": [
|
2024-02-18 05:56:33 +08:00
|
|
|
4866, 4867, 4865, 49196, 49200, 159, 52393, 52392, 52394, 49195, 49199,
|
|
|
|
158, 49188, 49192, 107, 49187, 49191, 103, 49162, 49172, 57, 49161,
|
|
|
|
49171, 51, 157, 156, 61, 60, 53, 47, 255
|
2024-01-25 12:01:53 +08:00
|
|
|
],
|
|
|
|
"compression": "AA==",
|
|
|
|
"random": "UqfPi+EmtMgusILrKcELvVWwpOdPSM/My09nPXl84dg=",
|
|
|
|
"session": "jCTrpAzHpwrfuYdYx4FEjZwbcQxCuZ52HGIoOcbw1vA=",
|
|
|
|
"sni": "ipinfo.io",
|
2024-02-18 05:56:33 +08:00
|
|
|
"supported_versions": [772, 771],
|
2024-01-26 12:54:20 +08:00
|
|
|
"version": 771,
|
|
|
|
"ech": true
|
2024-01-25 12:01:53 +08:00
|
|
|
},
|
|
|
|
"resp": {
|
|
|
|
"cipher": 4866,
|
|
|
|
"compression": 0,
|
|
|
|
"random": "R/Cy1m9pktuBMZQIHahD8Y83UWPRf8j8luwNQep9yJI=",
|
|
|
|
"session": "jCTrpAzHpwrfuYdYx4FEjZwbcQxCuZ52HGIoOcbw1vA=",
|
|
|
|
"supported_versions": 772,
|
|
|
|
"version": 771
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking TLS connections to `ipinfo.io`:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block ipinfo.io TLS
|
|
|
|
action: block
|
|
|
|
expr: tls != nil && tls.req != nil && tls.req.sni == "ipinfo.io"
|
|
|
|
```
|
|
|
|
|
2024-02-18 05:56:33 +08:00
|
|
|
## QUIC
|
|
|
|
|
|
|
|
QUIC analyzer produces the same result format as TLS analyzer, but currently only supports "req" direction (client
|
|
|
|
hello), not "resp" (server hello).
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"quic": {
|
|
|
|
"req": {
|
|
|
|
"alpn": ["h3"],
|
|
|
|
"ciphers": [4865, 4866, 4867],
|
|
|
|
"compression": "AA==",
|
|
|
|
"ech": true,
|
|
|
|
"random": "FUYLceFReLJl9dRQ0HAus7fi2ZGuKIAApF4keeUqg00=",
|
|
|
|
"session": "",
|
|
|
|
"sni": "quic.rocks",
|
|
|
|
"supported_versions": [772],
|
|
|
|
"version": 771
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking QUIC connections to `quic.rocks`:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block quic.rocks QUIC
|
|
|
|
action: block
|
|
|
|
expr: quic != nil && quic.req != nil && quic.req.sni == "quic.rocks"
|
|
|
|
```
|
|
|
|
|
2024-01-25 12:01:53 +08:00
|
|
|
## Trojan (proxy protocol)
|
|
|
|
|
|
|
|
Check https://github.com/XTLS/Trojan-killer for more information.
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"trojan": {
|
|
|
|
"down": 4712,
|
|
|
|
"up": 671,
|
|
|
|
"yes": true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking Trojan connections:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
- name: Block Trojan
|
|
|
|
action: block
|
|
|
|
expr: trojan != nil && trojan.yes
|
2024-01-26 14:45:26 +08:00
|
|
|
```
|
|
|
|
|
2024-01-27 20:59:41 +08:00
|
|
|
## SOCKS
|
2024-01-27 14:09:21 +08:00
|
|
|
|
|
|
|
SOCKS4:
|
|
|
|
|
2024-02-18 05:56:33 +08:00
|
|
|
```json
|
2024-01-27 14:09:21 +08:00
|
|
|
{
|
2024-01-27 20:59:41 +08:00
|
|
|
"socks": {
|
|
|
|
"version": 4,
|
2024-01-27 14:09:21 +08:00
|
|
|
"req": {
|
2024-01-27 20:59:41 +08:00
|
|
|
"cmd": 1,
|
2024-02-18 05:56:33 +08:00
|
|
|
"addr_type": 1, // same as socks5
|
2024-01-27 20:59:41 +08:00
|
|
|
"addr": "1.1.1.1",
|
|
|
|
// for socks4a
|
|
|
|
// "addr_type": 3,
|
|
|
|
// "addr": "google.com",
|
2024-01-27 14:09:21 +08:00
|
|
|
"port": 443,
|
2024-01-27 20:59:41 +08:00
|
|
|
"auth": {
|
|
|
|
"user_id": "user"
|
|
|
|
}
|
2024-01-27 14:09:21 +08:00
|
|
|
},
|
|
|
|
"resp": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"rep": 90, // 0x5A(90) granted
|
2024-01-27 20:59:41 +08:00
|
|
|
"addr_type": 1,
|
|
|
|
"addr": "1.1.1.1",
|
2024-01-27 14:09:21 +08:00
|
|
|
"port": 443
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2024-01-27 05:57:15 +08:00
|
|
|
SOCKS5 without auth:
|
2024-01-26 14:45:26 +08:00
|
|
|
|
2024-02-18 05:56:33 +08:00
|
|
|
```json
|
2024-01-26 14:45:26 +08:00
|
|
|
{
|
2024-01-27 20:59:41 +08:00
|
|
|
"socks": {
|
|
|
|
"version": 5,
|
2024-01-26 14:45:26 +08:00
|
|
|
"req": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"cmd": 1, // 0x01: connect, 0x02: bind, 0x03: udp
|
|
|
|
"addr_type": 3, // 0x01: ipv4, 0x03: domain, 0x04: ipv6
|
2024-01-26 14:45:26 +08:00
|
|
|
"addr": "google.com",
|
|
|
|
"port": 80,
|
|
|
|
"auth": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"method": 0 // 0x00: no auth, 0x02: username/password
|
2024-01-26 14:45:26 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
"resp": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"rep": 0, // 0x00: success
|
|
|
|
"addr_type": 1, // 0x01: ipv4, 0x03: domain, 0x04: ipv6
|
2024-01-26 14:45:26 +08:00
|
|
|
"addr": "198.18.1.31",
|
|
|
|
"port": 80,
|
|
|
|
"auth": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"method": 0 // 0x00: no auth, 0x02: username/password
|
2024-01-26 14:45:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2024-01-27 05:57:15 +08:00
|
|
|
SOCKS5 with auth:
|
2024-01-26 14:45:26 +08:00
|
|
|
|
2024-02-18 05:56:33 +08:00
|
|
|
```json
|
2024-01-26 14:45:26 +08:00
|
|
|
{
|
2024-01-27 20:59:41 +08:00
|
|
|
"socks": {
|
|
|
|
"version": 5,
|
2024-01-26 14:45:26 +08:00
|
|
|
"req": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"cmd": 1, // 0x01: connect, 0x02: bind, 0x03: udp
|
|
|
|
"addr_type": 3, // 0x01: ipv4, 0x03: domain, 0x04: ipv6
|
2024-01-26 14:45:26 +08:00
|
|
|
"addr": "google.com",
|
|
|
|
"port": 80,
|
|
|
|
"auth": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"method": 2, // 0x00: no auth, 0x02: username/password
|
2024-01-26 14:45:26 +08:00
|
|
|
"username": "user",
|
|
|
|
"password": "pass"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"resp": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"rep": 0, // 0x00: success
|
|
|
|
"addr_type": 1, // 0x01: ipv4, 0x03: domain, 0x04: ipv6
|
2024-01-26 14:45:26 +08:00
|
|
|
"addr": "198.18.1.31",
|
|
|
|
"port": 80,
|
|
|
|
"auth": {
|
2024-02-18 05:56:33 +08:00
|
|
|
"method": 2, // 0x00: no auth, 0x02: username/password
|
|
|
|
"status": 0 // 0x00: success, 0x01: failure
|
2024-01-26 14:45:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2024-01-27 05:57:15 +08:00
|
|
|
Example for blocking connections to `google.com:80` and user `foobar`:
|
2024-01-26 14:45:26 +08:00
|
|
|
|
|
|
|
```yaml
|
2024-01-27 20:59:41 +08:00
|
|
|
- name: Block SOCKS google.com:80
|
2024-01-26 14:45:26 +08:00
|
|
|
action: block
|
2024-01-27 20:59:41 +08:00
|
|
|
expr: string(socks?.req?.addr) endsWith "google.com" && socks?.req?.port == 80
|
2024-01-26 14:45:26 +08:00
|
|
|
|
2024-01-27 20:59:41 +08:00
|
|
|
- name: Block SOCKS user foobar
|
2024-01-26 14:45:26 +08:00
|
|
|
action: block
|
2024-01-27 20:59:41 +08:00
|
|
|
expr: socks?.req?.auth?.method == 2 && socks?.req?.auth?.username == "foobar"
|
2024-01-26 14:45:26 +08:00
|
|
|
```
|
2024-01-31 10:05:51 +08:00
|
|
|
|
|
|
|
## WireGuard
|
|
|
|
|
2024-02-18 05:56:33 +08:00
|
|
|
```json
|
2024-01-31 10:05:51 +08:00
|
|
|
{
|
|
|
|
"wireguard": {
|
|
|
|
"message_type": 1, // 0x1: handshake_initiation, 0x2: handshake_response, 0x3: packet_cookie_reply, 0x4: packet_data
|
|
|
|
"handshake_initiation": {
|
|
|
|
"sender_index": 0x12345678
|
|
|
|
},
|
|
|
|
"handshake_response": {
|
|
|
|
"sender_index": 0x12345678,
|
|
|
|
"receiver_index": 0x87654321,
|
|
|
|
"receiver_index_matched": true
|
|
|
|
},
|
|
|
|
"packet_data": {
|
|
|
|
"receiver_index": 0x12345678,
|
|
|
|
"receiver_index_matched": true
|
|
|
|
},
|
|
|
|
"packet_cookie_reply": {
|
|
|
|
"receiver_index": 0x12345678,
|
|
|
|
"receiver_index_matched": true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Example for blocking WireGuard traffic:
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
# false positive: high
|
|
|
|
- name: Block all WireGuard-like traffic
|
|
|
|
action: block
|
|
|
|
expr: wireguard != nil
|
|
|
|
|
|
|
|
# false positive: medium
|
|
|
|
- name: Block WireGuard by handshake_initiation
|
|
|
|
action: drop
|
|
|
|
expr: wireguard?.handshake_initiation != nil
|
|
|
|
|
|
|
|
# false positive: low
|
|
|
|
- name: Block WireGuard by handshake_response
|
|
|
|
action: drop
|
|
|
|
expr: wireguard?.handshake_response?.receiver_index_matched == true
|
|
|
|
|
|
|
|
# false positive: pretty low
|
|
|
|
- name: Block WireGuard by packet_data
|
|
|
|
action: block
|
|
|
|
expr: wireguard?.packet_data?.receiver_index_matched == true
|
|
|
|
```
|