add socks_decoder, stratum_decoder and session_flags
This commit is contained in:
123
decoders/session_flags/fet.cpp
Normal file
123
decoders/session_flags/fet.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*ref: https://github.com/apernet/OpenGFW/blob/1dce82745d0bc8b3813aea147954ba3a2294ef30/analyzer/tcp/fet.go
|
||||
https://www.usenix.org/system/files/usenixsecurity23-wu-mingshi.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "fet.h"
|
||||
|
||||
bool isPrintable(unsigned char b) {
|
||||
return b >= 0x20 && b <= 0x7e;
|
||||
}
|
||||
|
||||
int popCount(unsigned char b) {
|
||||
int count = 0;
|
||||
while (b != 0) {
|
||||
count += (int)(b & 1);
|
||||
b >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
float averagePopCount(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < bytes_len; i++) {
|
||||
total += popCount(bytes[i]);
|
||||
}
|
||||
return (float)total / (float)bytes_len;
|
||||
}
|
||||
|
||||
bool isFirstSixPrintable(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len < 6) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (!isPrintable(bytes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float printablePercentage(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (int i = 0; i < bytes_len; i++) {
|
||||
if (isPrintable(bytes[i])) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return (float)count / (float)bytes_len;
|
||||
}
|
||||
|
||||
int contiguousPrintable(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
int maxCount = 0;
|
||||
int current = 0;
|
||||
for (int i = 0; i < bytes_len; i++) {
|
||||
if (isPrintable(bytes[i])) {
|
||||
current++;
|
||||
} else {
|
||||
if (current > maxCount) {
|
||||
maxCount = current;
|
||||
}
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
if (current > maxCount) {
|
||||
maxCount = current;
|
||||
}
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
bool isTLS(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len < 3) {
|
||||
return false;
|
||||
}
|
||||
// "We observe that the GFW exempts any connection whose first
|
||||
// three bytes match the following regular expression:
|
||||
// [\x16-\x17]\x03[\x00-\x09]" - from the paper in Section 4.3
|
||||
if (bytes[0] >= 0x16 && bytes[0] <= 0x17 &&
|
||||
bytes[1] == 0x03 && bytes[2] <= 0x09) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isHTTP(const unsigned char* bytes, int bytes_len) {
|
||||
if (bytes_len < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// HTTP request
|
||||
bool result = memcmp(bytes, "GET", 3) == 0 || memcmp(bytes, "HEA", 3) == 0 || memcmp(bytes, "POS", 3) == 0 ||
|
||||
memcmp(bytes, "PUT", 3) == 0 || memcmp(bytes, "DEL", 3) == 0 || memcmp(bytes, "CON", 3) == 0 ||
|
||||
memcmp(bytes, "OPT", 3) == 0 || memcmp(bytes, "TRA", 3) == 0 || memcmp(bytes, "PAT", 3) == 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int is_data_fet(unsigned char* data, int data_len, struct fet_detail* detail) {
|
||||
if (data_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
float ex1 = averagePopCount(data, data_len);
|
||||
bool ex2 = isFirstSixPrintable(data, data_len);
|
||||
float ex3 = printablePercentage(data, data_len);
|
||||
int ex4 = contiguousPrintable(data, data_len);
|
||||
bool ex5 = isTLS(data, data_len);
|
||||
bool ex6 = isHTTP(data, data_len);
|
||||
bool exempt = (ex1 <= 3.4 || ex1 >= 4.6) || ex2 || ex3 > 0.5 || ex4 > 20 || ex5 || ex6;
|
||||
|
||||
detail->is_tls = ex5;
|
||||
|
||||
return !exempt;
|
||||
}
|
||||
Reference in New Issue
Block a user