kni适配firewall

This commit is contained in:
崔一鸣
2019-11-15 20:48:23 +08:00
parent 9e42ae3596
commit 3b81b3f083
11 changed files with 548 additions and 1396 deletions

View File

@@ -1,4 +1,4 @@
add_library(common STATIC src/kni_utils.cpp src/ssl_utils.cpp src/kni_cmsg.cpp)
add_library(common STATIC src/kni_utils.cpp src/kni_cmsg.cpp)
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(common MESA_handle_logger)

View File

@@ -22,7 +22,6 @@
#define KNI_STRING_MAX 2048
#define KNI_PATH_MAX 256
#define KNI_SYMBOL_MAX 64
#define KNI_DOMAIN_MAX 256
#define KNI_ADDR_MAX 128
#ifndef MAX
@@ -71,26 +70,20 @@ struct kni_tcpopt_info{
#define KNI_FS_COLUMN_MAX 256
#define KNI_FS_LINE_MAX 256
enum kni_field{
KNI_FIELD_BYP_STM,
KNI_FIELD_BYP_STM_POLICY,
KNI_FIELD_BYP_STM_ERR,
//stream error
KNI_FIELD_STMERR_ASYM_ROUTING,
KNI_FIELD_STMERR_NO_SYN,
KNI_FIELD_STMERR_NO_SYN_ACK,
KNI_FIELD_STMERR_NO_DATA,
KNI_FIELD_STMERR_UNSUPPORTED_PROTOCOL,
KNI_FIELD_STMERR_INVALID_IP_HDR,
KNI_FIELD_STMERR_EXCEED_MTU,
//stream error: internal error
KNI_FIELD_STMERR_INVALID_ACTION,
KNI_FIELD_STMERR_SENDTO_TFE_FAIL,
KNI_FIELD_STMERR_TUPLE2STM_ADD_FAIL,
KNI_FIELD_STMERR_NO_TFE,
KNI_FIELD_STMERR_PME_INIT_FAIL,
KNI_FIELD_STMERR_DUP_TRAFFIC,
KNI_FIELD_STMERR_CMSG_ADD_FAIL,
//intercept stream
KNI_FIELD_BYP_INTCPERR,
//intercept error
KNI_FIELD_INTCPERR_ASYM_ROUTING,
KNI_FIELD_INTCPERR_NO_SYN,
KNI_FIELD_INTCPERR_NO_SYN_ACK,
KNI_FIELD_INTCPERR_INVALID_IP_HDR,
KNI_FIELD_INTCPERR_EXCEED_MTU,
//intercept error: internal error
KNI_FIELD_INTCPERR_SENDTO_TFE_FAIL,
KNI_FIELD_INTCPERR_TUPLE2STM_ADD_FAIL,
KNI_FIELD_INTCPERR_NO_TFE,
KNI_FIELD_INTCPERR_DUP_TRAFFIC,
KNI_FIELD_INTCPERR_CMSG_ADD_FAIL,
//success intercept stream
KNI_FIELD_INTCP_STM,
KNI_FIELD_INTCP_BYTE,
KNI_FIELD_SSL_STM,
@@ -154,6 +147,7 @@ struct pkt_info{
uint16_t tcphdr_len;
char *data;
uint16_t data_len;
int parse_failed;
};
enum kni_ipv4hdr_parse_error{

View File

@@ -1,34 +0,0 @@
#pragma once
struct cipher_suite
{
int value;
const char* name;
};
enum chello_parse_result
{
CHELLO_PARSE_SUCCESS = 0,
CHELLO_PARSE_INVALID_FORMAT = -1,
CHELLO_PARSE_NOT_ENOUGH_BUFF = -2
};
struct ssl_version
{
uint8_t minor;
uint8_t major;
uint16_t ossl_format;
};
struct ssl_chello
{
struct ssl_version min_version;
struct ssl_version max_version;
char* sni;
char* alpn;
char* cipher_suites;
char* cipher_suites_tls13;
};
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result);
void ssl_chello_free(struct ssl_chello* chello);

View File

@@ -1,466 +0,0 @@
#include "kni_utils.h"
#include "ssl_utils.h"
struct cipher_suite cipher_suite_list[] =
{
{0xC030, "ECDHE-RSA-AES256-GCM-SHA384"},
{0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"},
{0xC028, "ECDHE-RSA-AES256-SHA384"},
{0xC024, "ECDHE-ECDSA-AES256-SHA384"},
{0xC014, "ECDHE-RSA-AES256-SHA"},
{0xC00A, "ECDHE-ECDSA-AES256-SHA"},
{0x00A5, "DH-DSS-AES256-GCM-SHA384"},
{0x00A3, "DHE-DSS-AES256-GCM-SHA384"},
{0x00A1, "DH-RSA-AES256-GCM-SHA384"},
{0x009F, "DHE-RSA-AES256-GCM-SHA384"},
{0x006B, "DHE-RSA-AES256-SHA256"},
{0x006A, "DHE-DSS-AES256-SHA256"},
{0x0069, "DH-RSA-AES256-SHA256"},
{0x0068, "DH-DSS-AES256-SHA256"},
{0x0039, "DHE-RSA-AES256-SHA"},
{0x0038, "DHE-DSS-AES256-SHA"},
{0x0037, "DH-RSA-AES256-SHA"},
{0x0036, "DH-DSS-AES256-SHA"},
{0x0088, "DHE-RSA-CAMELLIA256-SHA"},
{0x0087, "DHE-DSS-CAMELLIA256-SHA"},
{0x0086, "DH-RSA-CAMELLIA256-SHA"},
{0x0085, "DH-DSS-CAMELLIA256-SHA"},
{0xC019, "AECDH-AES256-SHA"},
{0x00A7, "ADH-AES256-GCM-SHA384"},
{0x006D, "ADH-AES256-SHA256"},
{0x003A, "ADH-AES256-SHA"},
{0x0089, "ADH-CAMELLIA256-SHA"},
{0xC032, "ECDH-RSA-AES256-GCM-SHA384"},
{0xC02E, "ECDH-ECDSA-AES256-GCM-SHA384"},
{0xC02A, "ECDH-RSA-AES256-SHA384"},
{0xC026, "ECDH-ECDSA-AES256-SHA384"},
{0xC00F, "ECDH-RSA-AES256-SHA"},
{0xC005, "ECDH-ECDSA-AES256-SHA"},
{0x009D, "AES256-GCM-SHA384"},
{0x003D, "AES256-SHA256"},
{0x0035, "AES256-SHA"},
{0x0084, "CAMELLIA256-SHA"},
{0x008D, "PSK-AES256-CBC-SHA"},
{0xC02F, "ECDHE-RSA-AES128-GCM-SHA256"},
{0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"},
{0xC027, "ECDHE-RSA-AES128-SHA256"},
{0xC023, "ECDHE-ECDSA-AES128-SHA256"},
{0xC013, "ECDHE-RSA-AES128-SHA"},
{0xC009, "ECDHE-ECDSA-AES128-SHA"},
{0x00A4, "DH-DSS-AES128-GCM-SHA256"},
{0x00A2, "DHE-DSS-AES128-GCM-SHA256"},
{0x00A0, "DH-RSA-AES128-GCM-SHA256"},
{0x009E, "DHE-RSA-AES128-GCM-SHA256"},
{0x0067, "DHE-RSA-AES128-SHA256"},
{0x0040, "DHE-DSS-AES128-SHA256"},
{0x003F, "DH-RSA-AES128-SHA256"},
{0x003E, "DH-DSS-AES128-SHA256"},
{0x0033, "DHE-RSA-AES128-SHA"},
{0x0032, "DHE-DSS-AES128-SHA"},
{0x0031, "DH-RSA-AES128-SHA"},
{0x0030, "DH-DSS-AES128-SHA"},
{0x009A, "DHE-RSA-SEED-SHA"},
{0x0099, "DHE-DSS-SEED-SHA"},
{0x0098, "DH-RSA-SEED-SHA"},
{0x0097, "DH-DSS-SEED-SHA"},
{0x0045, "DHE-RSA-CAMELLIA128-SHA"},
{0x0044, "DHE-DSS-CAMELLIA128-SHA"},
{0x0043, "DH-RSA-CAMELLIA128-SHA"},
{0x0042, "DH-DSS-CAMELLIA128-SHA"},
{0xC018, "AECDH-AES128-SHA"},
{0x00A6, "ADH-AES128-GCM-SHA256"},
{0x006C, "ADH-AES128-SHA256"},
{0x0034, "ADH-AES128-SHA"},
{0x009B, "ADH-SEED-SHA"},
{0x0046, "ADH-CAMELLIA128-SHA"},
{0xC031, "ECDH-RSA-AES128-GCM-SHA256"},
{0xC02D, "ECDH-ECDSA-AES128-GCM-SHA256"},
{0xC029, "ECDH-RSA-AES128-SHA256"},
{0xC025, "ECDH-ECDSA-AES128-SHA256"},
{0xC00E, "ECDH-RSA-AES128-SHA"},
{0xC004, "ECDH-ECDSA-AES128-SHA"},
{0x009C, "AES128-GCM-SHA256"},
{0x003C, "AES128-SHA256"},
{0x002F, "AES128-SHA"},
{0x0096, "SEED-SHA"},
{0x0041, "CAMELLIA128-SHA"},
{0x008C, "PSK-AES128-CBC-SHA"},
{0xC012, "ECDHE-RSA-DES-CBC3-SHA"},
{0xC008, "ECDHE-ECDSA-DES-CBC3-SHA"},
{0x0016, "EDH-RSA-DES-CBC3-SHA"},
{0x0013, "EDH-DSS-DES-CBC3-SHA"},
{0x0010, "DH-RSA-DES-CBC3-SHA"},
{0x000D, "DH-DSS-DES-CBC3-SHA"},
{0xC017, "AECDH-DES-CBC3-SHA"},
{0x001B, "ADH-DES-CBC3-SHA"},
{0xC00D, "ECDH-RSA-DES-CBC3-SHA"},
{0xC003, "ECDH-ECDSA-DES-CBC3-SHA"},
{0x000A, "DES-CBC3-SHA"},
{0x0007, "IDEA-CBC-SHA"},
{0x008B, "PSK-3DES-EDE-CBC-SHA"},
{0x0021, "KRB5-IDEA-CBC-SHA"},
{0x001F, "KRB5-DES-CBC3-SHA"},
{0x0025, "KRB5-IDEA-CBC-MD5"},
{0x0023, "KRB5-DES-CBC3-MD5"},
{0xC011, "ECDHE-RSA-RC4-SHA"},
{0xC007, "ECDHE-ECDSA-RC4-SHA"},
{0xC016, "AECDH-RC4-SHA"},
{0x0018, "ADH-RC4-MD5"},
{0xC00C, "ECDH-RSA-RC4-SHA"},
{0xC002, "ECDH-ECDSA-RC4-SHA"},
{0x0005, "RC4-SHA"},
{0x0004, "RC4-MD5"},
{0x008A, "PSK-RC4-SHA"},
{0x0020, "KRB5-RC4-SHA"},
{0x0024, "KRB5-RC4-MD5"},
{0xC010, "ECDHE-RSA-NULL-SHA"},
{0xC006, "ECDHE-ECDSA-NULL-SHA"},
{0xC015, "AECDH-NULL-SHA"},
{0xC00B, "ECDH-RSA-NULL-SHA"},
{0xC001, "ECDH-ECDSA-NULL-SHA"},
{0x003B, "NULL-SHA256"},
{0x0002, "NULL-SHA"},
{0x0001, "NULL-MD5"}
};
struct cipher_suite cipher_suite_list_tls13[] =
{
{0x1301, "TLS_AES_128_GCM_SHA256"},
{0x1302, "TLS_AES_256_GCM_SHA384"},
{0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
{0x1304, "TLS_AES_128_CCM_SHA256"},
{0x1305, "TLS_AES_128_CCM_8_SHA256"}
};
void ssl_chello_free(struct ssl_chello* chello)
{
if(chello==NULL)
{
return;
}
free(chello->sni);
chello->sni = NULL;
free(chello->alpn);
chello->alpn = NULL;
free(chello->cipher_suites);
chello->cipher_suites = NULL;
free(chello->cipher_suites_tls13);
chello->cipher_suites_tls13 = NULL;
free(chello);
}
static char* parse_alpn_extension(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
{
size_t pos = 0;
size_t len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
if(2 + len != buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return NULL;
}
char* alpn = ALLOC(char, len + 1);
strncpy((char*)alpn, (const char*)buff + 2, len);
alpn[len] = '\0';
*result = CHELLO_PARSE_SUCCESS;
return alpn;
}
static char* parse_server_name_extension(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
{
size_t pos = 2; /* skip server name list length */
size_t len;
char* sni = NULL;
while (pos + 3 < buff_len)
{
len = ((size_t)buff[pos + 1] << 8) + (size_t)buff[pos + 2];
if (pos + 3 + len > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return NULL;
}
switch (buff[pos])
{
case 0x00: /* host_name */
sni = (char*)malloc(len + 1);
strncpy(sni, (const char*)buff + pos + 3, len);
sni[len] = '\0';
*result = CHELLO_PARSE_SUCCESS;
}
pos += 3 + len;
}
if (pos != buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
}
return sni;
}
static enum chello_parse_result parse_extensions(const unsigned char* buff, size_t buff_len, struct ssl_chello* chello) {
size_t pos = 0;
/* Parse each 4 bytes for the extension header */
while (pos + 4 <= buff_len)
{
size_t len = ((size_t)buff[pos + 2] << 8) + (size_t)buff[pos + 3];
/* Check if it's a server name extension */
if (buff[pos] == 0x00 && buff[pos + 1] == 0x00)
{
if (pos + 4 + len > buff_len)
{
return CHELLO_PARSE_INVALID_FORMAT;
}
enum chello_parse_result result = CHELLO_PARSE_SUCCESS;
chello->sni = parse_server_name_extension(buff + pos + 4, len, &result);
if(result != CHELLO_PARSE_SUCCESS)
{
return result;
}
}
/* Check if it's a alpn extension */
if (buff[pos] == 0x00 && buff[pos + 1] == 0x10)
{
if (pos + 4 + len > buff_len)
{
return CHELLO_PARSE_INVALID_FORMAT;
}
enum chello_parse_result result = CHELLO_PARSE_SUCCESS;
chello->alpn = parse_alpn_extension(buff + pos + 4, len, &result);
if(result != CHELLO_PARSE_SUCCESS)
{
return result;
}
}
pos += (4 + len);
}
/* Check we ended where we expected to */
if (pos != buff_len)
{
return CHELLO_PARSE_INVALID_FORMAT;
}
return CHELLO_PARSE_SUCCESS;
}
static char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n, const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
{
char* cipher_suites_str = (char* )malloc(KNI_STRING_MAX);
cipher_suites_str[0] = '\0';
size_t pos = 0;
int flag = 0;
while(pos < buff_len)
{
int i = 0;
for(i = 0;i < n; i++)
{
int val = (buff[pos] << 8) + buff[pos + 1];
if(_cipher_suite_list[i].value == val)
{
if(strnlen(_cipher_suite_list[i].name, KNI_STRING_MAX) + strnlen(cipher_suites_str, KNI_STRING_MAX) + 1 > KNI_STRING_MAX)
{
flag = 1;
break;
}
strncat(cipher_suites_str, _cipher_suite_list[i].name, KNI_STRING_MAX);
strncat(cipher_suites_str, ":", KNI_STRING_MAX);
}
}
pos += 2;
if(flag == 1)
{
break;
}
}
int len = strnlen(cipher_suites_str, KNI_STRING_MAX);
if(len > 0)
{
cipher_suites_str[len-1] = '\0';
}
if(pos != buff_len && flag == 0)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
free(cipher_suites_str);
return NULL;
}
*result = CHELLO_PARSE_SUCCESS;
return cipher_suites_str;
}
struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum chello_parse_result* result)
{
if(buff == NULL)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return NULL;
}
if(buff_len < 1)
{
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
return NULL;
}
if(buff[0] != 0x80 && buff[0] != 0x16)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return NULL;
}
/* SSL 2.0 compatible Client Hello
* High bit of first byte (length) and content type is Client Hello
* See RFC5246 Appendix E.2
* if it is SSL 2.0, only parse version
*/
if(buff[0] == 0x80)
{
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
_chello->min_version.major = 0x02;
if(buff_len < 2)
{
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
return _chello;
}
size_t len = (size_t)buff[1];
if (buff_len < len + 2)
{
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
return _chello;
}
buff_len = len + 2;
size_t pos = 2;
/* Handshark Message Type: Client Hello */
if (pos + 1 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
if (buff[pos] != 0x01)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
pos += 1;
/* Version */
if(pos + 2 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
_chello->max_version.major = buff[pos];
_chello->max_version.minor = buff[pos + 1];
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
*result = CHELLO_PARSE_SUCCESS;
return _chello;
}
else
{
if (buff_len < 5)
{
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
return NULL;
}
if(buff[1] != 3 || buff[2] > 4 || buff[2] < 0)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return NULL;
}
struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1);
_chello->min_version.major = buff[1];
_chello->min_version.minor = buff[2];
_chello->min_version.ossl_format=(uint16_t)_chello->min_version.major<<8|_chello->min_version.minor;
_chello->max_version.major = -1;
_chello->max_version.minor = -1;
_chello->sni = NULL;
_chello->alpn = NULL;
_chello->cipher_suites = NULL;
_chello->cipher_suites_tls13 = NULL;
/* TLS record length */
size_t len = ((size_t)buff[3] << 8) + (size_t)buff[4] + 5;
if (buff_len < len)
{
*result = CHELLO_PARSE_NOT_ENOUGH_BUFF;
return _chello;
}
buff_len = len;
size_t pos = 5;
if (pos + 1 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
if (buff[pos] != 0x01)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
pos += 4;
if(pos + 2 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
_chello->max_version.major = buff[pos];
_chello->max_version.minor = buff[pos+1];
_chello->max_version.ossl_format=(uint16_t)_chello->max_version.major<<8|_chello->max_version.minor;
pos += 34;
/* Session ID */
if (pos + 1 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
len = (size_t)buff[pos];
pos += 1 + len;
/* Cipher Suites */
if (pos + 2 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
pos += 2;
if(pos + len > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
int n = sizeof(cipher_suite_list) / sizeof(struct cipher_suite);
_chello->cipher_suites = parse_cipher_suites(cipher_suite_list, n, buff + pos, len, result);
if(*result != CHELLO_PARSE_SUCCESS)
{
return _chello;
}
n = sizeof(cipher_suite_list_tls13) / sizeof(struct cipher_suite);
_chello->cipher_suites_tls13 = parse_cipher_suites(cipher_suite_list_tls13, n, buff + pos, len, result);
if(*result != CHELLO_PARSE_SUCCESS)
{
return _chello;
}
pos += len;
/* Compression Methods */
if (pos >= buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
len = (size_t)buff[pos];
pos += 1 + len;
/* no extensions */
if(pos == buff_len)
{
*result = CHELLO_PARSE_SUCCESS;
return _chello;
}
/* Extensions */
if (pos + 2 > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1];
pos += 2;
if (pos + len > buff_len)
{
*result = CHELLO_PARSE_INVALID_FORMAT;
return _chello;
}
enum chello_parse_result ret = parse_extensions(buff + pos, len, _chello);
*result = ret;
return _chello;
}
}

View File

@@ -100,3 +100,4 @@ remote_ip = 192.168.10.152
remote_port = 8125
local_path = ./fs2_kni.status
stat_cycle = 2
print_mode = 1

View File

@@ -1,3 +1,3 @@
add_library(kni SHARED src/kni_entry.cpp src/kni_maat.cpp src/kni_send_logger.cpp src/tfe_mgr.cpp src/kni_tun.cpp)
add_library(kni SHARED src/kni_entry.cpp src/kni_send_logger.cpp src/tfe_mgr.cpp src/kni_tun.cpp)
target_include_directories(kni PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(kni common MESA_prof_load MESA_htable MESA_field_stat maatframe marsio uuid cjson rdkafka dabloom)

View File

@@ -1,32 +0,0 @@
#pragma once
#define KNI_MAAT_READCONF_IRIS 0
#define KNI_MAAT_READCONF_JSON 1
#define KNI_MAAT_READCONF_REDIS 2
#define KNI_MAAT_RULE_NUM_MAX 8
struct kni_maat_handle;
/* action
0x00: none
0x01: monitor
0x02: intercept
0x10: reject
0x30: Manipulate
0x60: steer
0x80: bypass
*/
enum kni_action{
KNI_ACTION_NONE = 0x00,
KNI_ACTION_MONITOR = 0x01,
KNI_ACTION_INTERCEPT = 0x02,
KNI_ACTION_REJECT = 0x10,
KNI_ACTION_MANIPULATE = 0x30,
KNI_ACTION_STEER = 0x60,
KNI_ACTION_BYPASS = 0x80
};
struct kni_maat_handle* kni_maat_init(const char* profile, void *logger, int thread_count);
void kni_maat_destroy(struct kni_maat_handle *handle);
enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipaddr *addr, char *domain, int domain_len,
int thread_seq, int *policy_id, int *do_log, int *is_hit_policy);
char* kni_maat_action_trans(enum kni_action action);

46
entry/include/tsg_rule.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef __TSG_RULE_H__
#define __TSG_RULE_H__
#include <MESA/Maat_rule.h>
#include "tsg_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define MAX_DOAMIN_LEN 2048
struct _identify_info
{
tsg_protocol_t proto; //enum _tsg_protocol (tsg_types.h)
int domain_len;
char domain[MAX_DOAMIN_LEN];
};
typedef enum _PULL_RESULT_TYPE
{
PULL_KNI_RESULT,
PULL_FW_RESULT
}PULL_RESULT_TYPE;
extern Maat_feather_t g_tsg_maat_feather;
int tsg_rule_init(const char *conffile);
int tsg_scan_nesting_addr(Maat_feather_t maat_feather, const struct streaminfo *a_stream, tsg_protocol_t proto, scan_status_t *mid, Maat_rule_t*result, int result_num);
//return 0 if failed, return >0 on success;
int tsg_pull_policy_result(struct streaminfo *a_stream, PULL_RESULT_TYPE pull_result_type, Maat_rule_t *result, int result_num, struct _identify_info *identify_info);
//return -1 if failed, return 0 on success;
int tsg_shared_table_init(const char *conffile, Maat_feather_t maat_feather, void *logger);
//return value: -1: failed, 0: not hit, >0: hit count
int tsg_scan_shared_policy(Maat_feather_t maat_feather, void *pkt, int pkt_len, Maat_rule_t *result, int result_num, struct _identify_info *identify_info, scan_status_t *mid, void *logger, int thread_seq);
#ifdef __cplusplus
}
#endif
#endif

109
entry/include/tsg_types.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef __TSG_TYPES_H__
#define __TSG_TYPES_H__
typedef enum _tsg_opt
{
LOG_OPT_HTTP_URL=1,
LOG_OPT_HTTP_HOST,
LOG_OPT_HTTP_REQUEST_LINE,
LOG_OPT_HTTP_RESPONSE_LINE,
LOG_OPT_HTTP_REQUEST_HEADER,
LOG_OPT_HTTP_RESPONSE_HEADER,
LOG_OPT_HTTP_REQUEST_BODY,
LOG_OPT_HTTP_RESPONSE_BODY,
LOG_OPT_HTTP_PROXY_FLAG,
LOG_OPT_HTTP_SEQUENCE,
LOG_OPT_HTTP_SNAPSHOT,
LOG_OPT_HTTP_COOKIE,
LOG_OPT_HTTP_REFERER,
LOG_OPT_HTTP_USER_AGENT,
LOG_OPT_HTTP_CONTENT_LENGTH,
LOG_OPT_HTTP_CONTENT_TYPE,
LOG_OPT_HTTP_SET_COOKIE,
LOG_OPT_HTTP_VERSION,
LOG_OPT_MAIL_PROTOCOL_TYPE,
LOG_OPT_MAIL_SENDER,
LOG_OPT_MAIL_RECEIVER,
LOG_OPT_MAIL_SUBJECT,
LOG_OPT_MAIL_CONTENT,
LOG_OPT_MAIL_ATTACHMENT_NAME,
LOG_OPT_MAIL_ATTACHMENT_CONTENT,
LOG_OPT_MAIL_EML_FILE,
LOG_OPT_MAIL_SNAPSHOT,
LOG_OPT_MAIL_SUBJECT_CHARSET,
LOG_OPT_DNS_MESSAGE_ID,
LOG_OPT_DNS_QR,
LOG_OPT_DNS_OPCODE,
LOG_OPT_DNS_AA,
LOG_OPT_DNS_TC,
LOG_OPT_DNS_RD,
LOG_OPT_DNS_RA,
LOG_OPT_DNS_RCODE,
LOG_OPT_DNS_QDCOUNT,
LOG_OPT_DNS_ANCOUNT,
LOG_OPT_DNS_NSCOUNT,
LOG_OPT_DNS_ARCOUNT,
LOG_OPT_DNS_QNAME,
LOG_OPT_DNS_QTYPE,
LOG_OPT_DNS_QCLASS,
LOG_OPT_DNS_CNAME,
LOG_OPT_DNS_SUB,
LOG_OPT_DNS_RR,
LOG_OPT_SSL_VERSION,
LOG_OPT_SSL_SNI,
LOG_OPT_SSL_SAN,
LOG_OPT_SSL_CN,
LOG_OPT_SSL_PINNINGST,
LOG_OPT_SSL_INTERCEPT_STATE,
LOG_OPT_SSL_SERVER_SIDE_LATENCY,
LOG_OPT_SSL_CLINET_SIDE_LATENCY,
LOG_OPT_SSL_SERVER_SIDE_VERSION,
LOG_OPT_SSL_CLIENT_SIDE_VERSION,
LOG_OPT_SSL_CERT_VERIFY,
LOG_OPT_SSL_ERROR,
LOG_OPT_SSL_CON_LATENCY_MS,
LOG_OPT_FTP_URL,
LOG_OPT_FTP_CONTENT,
LOG_OPT_BGP_TYPE,
LOG_OPT_BGP_AS_NUM,
LOG_OPT_BGP_ROUTE,
LOG_OPT_VOIP_CALLING_ACCOUNT,
LOG_OPT_VOIP_CALLED_ACCOUNT,
LOG_OPT_VOIP_CALLING_NUMBER,
LOG_OPT_VOIP_CALLED_NUMBER,
LOG_OPT_RADIUS_PACKET_TYPE,
LOG_OPT_RADIUS_NAS_IP,
LOG_OPT_RADIUS_FRAMED_IP,
LOG_OPT_RADIUS_ACCOUNT,
LOG_OPT_RADIUS_SEESION_TIMEOUT,
LOG_OPT_RADIUS_IDLE_TIMEOUT,
LOG_OPT_RADIUS_ACCT_STATUS_TYPE,
LOG_OPT_RADIUS_ACCT_TERMINATE_CAUSE,
LOG_OPT_MAX
}tsg_opt_t;
typedef enum _tsg_protocol
{
PROTO_IPv4,
PROTO_IPv6,
PROTO_TCP,
PROTO_UDP,
PROTO_HTTP,
PROTO_MAIL,
PROTO_DNS,
PROTO_FTP,
PROTO_SSL,
PROTO_SIP,
PROTO_BGP,
PROTO_STREAMING_MEDIA,
PROTO_MAX
}tsg_protocol_t;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,405 +0,0 @@
#include "kni_utils.h"
#include "kni_maat.h"
enum scan_table
{
PXY_INTERCEPT_IP,
PXY_INTERCEPT_DOMAIN,
TSG_OBJ_SUBSCRIBER_ID,
SCAN_TABLE_MAX
};
enum kni_action g_maat_default_action = KNI_ACTION_BYPASS;
int g_maat_default_log_option=1;
struct kni_maat_handle{
Maat_feather_t static_maat;
Maat_feather_t dynamic_maat;
int scan_tableid[SCAN_TABLE_MAX];
int subscriber_id_tableid;
void *logger;
};
void kni_maat_destroy(struct kni_maat_handle *handle){
if(handle != NULL){
if(handle->static_maat != NULL){
Maat_burn_feather(handle->static_maat);
}
if(handle->dynamic_maat != NULL){
Maat_burn_feather(handle->dynamic_maat);
}
}
FREE(&handle);
}
void compile_ex_param_new(int idx, const struct Maat_rule_t* rule, const char* srv_def_large, MAAT_RULE_EX_DATA* ad, long argl, void *argp){
void *logger = argp;
unsigned char tmp=0;
KNI_LOG_DEBUG(logger, "call compile_ex_param_new");
if(rule->config_id == 0){
tmp=(unsigned char)rule->action;
enum kni_action action = (enum kni_action)tmp;
if(action==KNI_ACTION_INTERCEPT)
{
g_maat_default_action = KNI_ACTION_INTERCEPT;
KNI_LOG_INFO(logger, "Set default intercept action to intercept.");
}
else
{
g_maat_default_action = KNI_ACTION_BYPASS;
KNI_LOG_INFO(logger, "Set default intercept action to bypass.");
}
g_maat_default_log_option=rule->do_log;
}
return;
}
void compile_ex_param_free(int idx, const struct Maat_rule_t* rule, const char* srv_def_large, MAAT_RULE_EX_DATA* ad, long argl, void *argp){
void *logger = argp;
KNI_LOG_DEBUG(logger, "call compile_ex_param_free");
return;
}
void compile_ex_param_dup(int idx, MAAT_RULE_EX_DATA *to, MAAT_RULE_EX_DATA *from, long argl, void *argp){
void *logger = argp;
KNI_LOG_DEBUG(logger, "call compile_ex_param_dup");
return;
}
static Maat_feather_t create_maat_feather(const char *instance_name, const char* profile, const char *section, void *logger, int thread_count){
int readconf_mode;
char tableinfo_path[KNI_PATH_MAX];
char maatjson_path[KNI_PATH_MAX];
char redis_ip[INET_ADDRSTRLEN];
int redis_port;
int redis_index;
Maat_feather_t feather = NULL;
int effective_interval_ms = 1000;//1s
int ret = MESA_load_profile_int_nodef(profile, section, "readconf_mode", &readconf_mode);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: readconf_mode not set, profile = %s, section = %s", profile, section);
goto error_out;
}
ret = MESA_load_profile_string_nodef(profile, section, "tableinfo_path", tableinfo_path, sizeof(tableinfo_path));
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: tableinfo_path not set, profile = %s, section = %s", profile, section);
goto error_out;
}
KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n readconf_mode: %d\n tableinfo_path: %s" , section, readconf_mode, tableinfo_path);
feather = Maat_feather(thread_count, tableinfo_path, logger);
if(feather == NULL){
KNI_LOG_ERROR(logger, "Failed at Maat_feather, max_thread_num = %d, tableinfo_path = %s", thread_count, tableinfo_path);
goto error_out;
}
Maat_set_feather_opt(feather, MAAT_OPT_INSTANCE_NAME, instance_name, strlen(instance_name) + 1);
Maat_set_feather_opt(feather, MAAT_OPT_EFFECT_INVERVAL_MS, &effective_interval_ms, sizeof(effective_interval_ms));
switch(readconf_mode){
case KNI_MAAT_READCONF_JSON:
ret = MESA_load_profile_string_nodef(profile, section, "maatjson_path", maatjson_path, sizeof(maatjson_path));
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: maatjson_path not set, profile = %s, section = %s", profile, section);
goto error_out;
}
KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n maatjson_path: %s", section, maatjson_path);
Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, maatjson_path, strlen(maatjson_path));
break;
case KNI_MAAT_READCONF_IRIS:
break;
case KNI_MAAT_READCONF_REDIS:
ret = MESA_load_profile_string_nodef(profile, section, "redis_ip", redis_ip, sizeof(redis_ip));
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: redis_ip not set, profile = %s, section = %s", profile, section);
goto error_out;
}
ret = MESA_load_profile_int_nodef(profile, section, "redis_port", &redis_port);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: redis_port not set, profile = %s, section = %s", profile, section);
goto error_out;
}
ret = MESA_load_profile_int_nodef(profile, section, "redis_index", &redis_index);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_prof_load: redis_index not set, profile = %s, section = %s", profile, section);
goto error_out;
}
KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n redis_ip: %s\n redis_port: %d\n redis_index: %d",
section, redis_ip, redis_port, redis_index);
Maat_set_feather_opt(feather, MAAT_OPT_REDIS_IP, (void*)redis_ip, strlen(redis_ip) + 1);
Maat_set_feather_opt(feather, MAAT_OPT_REDIS_PORT, (void*)&redis_port, sizeof(redis_port));
Maat_set_feather_opt(feather, MAAT_OPT_REDIS_INDEX, (void*)&redis_index, sizeof(redis_index));
break;
default:
break;
}
ret = Maat_initiate_feather(feather);
if(ret < 0){
KNI_LOG_ERROR(logger, "Failed at Maat_initiate_feather");
goto error_out;
}
return feather;
error_out:
if(feather != NULL){
Maat_burn_feather(feather);
}
return NULL;
}
//copy from tfe
static int get_column_pos(const char* line, int column_seq, size_t *offset, size_t *len){
const char* seps=" \t";
char* saveptr=NULL, *subtoken=NULL, *str=NULL;
char* dup_line=kni_strdup(line);
int i=0, ret=-1;
for (str = dup_line; ; str = NULL){
subtoken = strtok_r(str, seps, &saveptr);
if (subtoken == NULL)
break;
if(i==column_seq-1){
*offset=subtoken-dup_line;
*len=strlen(subtoken);
ret=0;
break;
}
i++;
}
free(dup_line);
return ret;
}
void subscribe_id_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA* to, MAAT_PLUGIN_EX_DATA* from, long argl, void* argp){
*to = kni_strdup((char*)*from);
return;
}
void subscribe_id_new_cb(int table_id, const char* key, const char* table_line, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp){
int ret = 0;
size_t subscribe_id_offset, len;
void *logger = argp;
ret = get_column_pos(table_line, 4, &subscribe_id_offset, &len);
if(ret<0){
KNI_LOG_ERROR(logger, "Add subscribe ID faild: %s", table_line);
return;
}
*ad = ALLOC(char, len+1);
memcpy(*ad, table_line+subscribe_id_offset, len);
KNI_LOG_INFO(logger, "Add subscribe ID: %s", (char*)*ad);
return;
}
void subscribe_id_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp){
void *logger = argp;
KNI_LOG_INFO(logger, "Delete subscribe ID: %s", (char*)*ad);
free(*ad);
*ad = NULL;
}
struct kni_maat_handle* kni_maat_init(const char* profile, void *logger, int thread_count){
struct kni_maat_handle *handle = ALLOC(struct kni_maat_handle, 1);
handle->logger = logger;
//static maat
const char *table_name[SCAN_TABLE_MAX];
char tablename_intercept_compile[] = "PXY_INTERCEPT_COMPILE";
char tablename_subscriber_id[] = "TSG_DYN_SUBSCRIBER_IP";
int ret, i;
handle->static_maat = create_maat_feather("static", profile, "static_maat", logger, thread_count);
if(handle->static_maat == NULL){
goto error_out;
}
table_name[PXY_INTERCEPT_IP] = "PXY_INTERCEPT_IP";
table_name[PXY_INTERCEPT_DOMAIN] = "PXY_INTERCEPT_DOMAIN";
table_name[TSG_OBJ_SUBSCRIBER_ID] = "TSG_OBJ_SUBSCRIBER_ID";
for(i = 0; i < SCAN_TABLE_MAX; i++){
handle->scan_tableid[i] = Maat_table_register(handle->static_maat, table_name[i]);
if(handle->scan_tableid[i] < 0){
KNI_LOG_ERROR(logger, "Failed at Maat_table_register, tablename = %s, ret = %d",
table_name[i], handle->scan_tableid[i]);
goto error_out;
}
}
//get_ex
ret = Maat_rule_get_ex_new_index(handle->static_maat, tablename_intercept_compile, compile_ex_param_new, compile_ex_param_free, compile_ex_param_dup, 0, logger);
if(ret < 0){
KNI_LOG_ERROR(logger, "Failed at Maat_rule_get_ex_new_index, tablename = %s, ret = %d", tablename_intercept_compile, ret);
goto error_out;
}
//dynamic maat register
handle->dynamic_maat = create_maat_feather("dynamic", profile, "dynamic_maat", logger, thread_count);
if(handle->dynamic_maat == NULL){
goto error_out;
}
handle->subscriber_id_tableid = Maat_table_register(handle->dynamic_maat, tablename_subscriber_id);
if(handle->subscriber_id_tableid < 0){
KNI_LOG_ERROR(logger, "Failed at Maat_table_register, tablename = %s, ret = %d",
tablename_subscriber_id, handle->subscriber_id_tableid);
goto error_out;
}
ret = Maat_plugin_EX_register(handle->dynamic_maat,
handle->subscriber_id_tableid,
subscribe_id_new_cb,
subscribe_id_free_cb,
subscribe_id_dup_cb,
NULL,
0,
logger);
if(ret != 0){
KNI_LOG_ERROR(NULL, "Failed at Maat_plugin_EX_register, tablename = %s, ret = %d", tablename_subscriber_id, ret);
goto error_out;
}
return handle;
error_out:
kni_maat_destroy(handle);
return NULL;
}
static int index_of_enforce_policy(struct Maat_rule_t* result, size_t size){
size_t i = 0;
int biggest_intercept_policy_id = -1, ret_intercept_idx = -1;
int biggest_bypass_policy_id = -1, ret_bypass_idx = -1;
for(i = 0; i < size; i++){
if((unsigned char)result[i].action == KNI_ACTION_BYPASS){
if(result[i].config_id > biggest_bypass_policy_id){
biggest_bypass_policy_id = result[i].config_id;
ret_bypass_idx = i;
}
}
else{
if(result[i].config_id > biggest_intercept_policy_id){
biggest_intercept_policy_id = result[i].config_id;
ret_intercept_idx = i;
}
}
}
if(biggest_bypass_policy_id != -1){
return ret_bypass_idx;
}
else{
return ret_intercept_idx;
}
}
//type: 0 : sip, 1 : dip
static void get_ip_from_ipaddr(struct ipaddr *addr, char *ip, int type){
if(addr->addrtype == ADDR_TYPE_IPV4){
struct stream_tuple4_v4 *v4 = addr->v4;
if(type == 0){
inet_ntop(AF_INET, &(v4->saddr), ip, INET_ADDRSTRLEN);
}
else{
inet_ntop(AF_INET, &(v4->daddr), ip, INET_ADDRSTRLEN);
}
}
else{
struct stream_tuple4_v6 *v6 = addr->v6;
if(type == 0){
inet_ntop(AF_INET6, v6->saddr, ip, INET6_ADDRSTRLEN);
}
else{
inet_ntop(AF_INET6, v6->daddr, ip, INET6_ADDRSTRLEN);
}
}
return;
}
enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipaddr *addr, char *domain, int domain_len,
int thread_seq, int *policy_id, int *do_log, int *is_hit_policy){
//return KNI_ACTION_INTERCEPT;
struct Maat_rule_t result[KNI_MAAT_RULE_NUM_MAX];
scan_status_t scan_mid = NULL;
int scan_ret = 0, hit_policy_cnt = 0, enforced_policy_idx = 0;
//scan subscribe_id
char sip[INET6_ADDRSTRLEN] = "";
char dip[INET6_ADDRSTRLEN] = "";
get_ip_from_ipaddr(addr, sip, 0);
get_ip_from_ipaddr(addr, dip, 1);
char* source_subscribe_id = NULL, *dest_subscribe_id = NULL;
source_subscribe_id = (char*)Maat_plugin_get_EX_data(handle->dynamic_maat, handle->subscriber_id_tableid, sip);
dest_subscribe_id = (char*)Maat_plugin_get_EX_data(handle->dynamic_maat, handle->subscriber_id_tableid, dip);
KNI_LOG_DEBUG(handle->logger, "sip = %s, source_subscribe_id = %s", sip, source_subscribe_id == NULL ? "null" : source_subscribe_id);
KNI_LOG_DEBUG(handle->logger, "dip = %s, dest_subscribe_id = %s", dip, dest_subscribe_id == NULL ? "null" : dest_subscribe_id);
if(source_subscribe_id != NULL){
scan_ret = Maat_full_scan_string(handle->static_maat, handle->scan_tableid[TSG_OBJ_SUBSCRIBER_ID],
CHARSET_UTF8, source_subscribe_id, strlen(source_subscribe_id),
result+hit_policy_cnt, NULL, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt,
&scan_mid, thread_seq);
KNI_LOG_DEBUG(handle->logger, "source_subscribe_id = %s, scan_ret = %d", source_subscribe_id, scan_ret);
if(scan_ret > 0){
hit_policy_cnt += scan_ret;
}
free(source_subscribe_id);
}
if(dest_subscribe_id != NULL){
scan_ret = Maat_full_scan_string(handle->static_maat, handle->scan_tableid[TSG_OBJ_SUBSCRIBER_ID],
CHARSET_UTF8, dest_subscribe_id, strlen(dest_subscribe_id),
result+hit_policy_cnt, NULL, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt,
&scan_mid, thread_seq);
KNI_LOG_DEBUG(handle->logger, "dest_subscribe_id = %s, scan_ret = %d", dest_subscribe_id, scan_ret);
if(scan_ret > 0){
hit_policy_cnt += scan_ret;
}
free(dest_subscribe_id);
}
//tcp: 6, udp: 17, can't be 0
scan_ret = Maat_scan_proto_addr(handle->static_maat, handle->scan_tableid[PXY_INTERCEPT_IP], addr, 6,
result+hit_policy_cnt, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt,
&scan_mid, thread_seq);
if(scan_ret > 0){
hit_policy_cnt += scan_ret;
}
scan_ret = Maat_full_scan_string(handle->static_maat, handle->scan_tableid[PXY_INTERCEPT_DOMAIN], CHARSET_UTF8,
domain, domain_len,
result+hit_policy_cnt, NULL, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt,
&scan_mid, thread_seq);
if(scan_ret > 0){
hit_policy_cnt += scan_ret;
}
Maat_clean_status(&scan_mid);
if(hit_policy_cnt > 0){
enforced_policy_idx = index_of_enforce_policy(result, hit_policy_cnt);
*policy_id = result[enforced_policy_idx].config_id;
*do_log = result[enforced_policy_idx].do_log;
*is_hit_policy = 1;
unsigned char action = (unsigned char)result[enforced_policy_idx].action;
return (enum kni_action)action;
}
else{
*policy_id = 0;
*do_log = g_maat_default_log_option;
return g_maat_default_action;
}
}
/* action
0x00: none
0x01: monitor
0x02: intercept
0x10: reject
0x30: Manipulate
0x60: steer
0x80: bypass
*/
char* kni_maat_action_trans(enum kni_action action){
switch(action){
case 0x00:
return (char*)"none";
case 0x01:
return (char*)"monitor";
case 0x02:
return (char*)"intercept";
case 0x10:
return (char*)"reject";
case 0x30:
return (char*)"manipulate";
case 0x60:
return (char*)"steer";
case 0x80:
return (char*)"bypass";
default:
return (char*)"unknown";
}
}