1
This commit is contained in:
161
linux_kernel/network.c
Normal file
161
linux_kernel/network.c
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "network.h"
|
||||
|
||||
void block_ip_address(size_t ip_address, size_t time_sec) {
|
||||
struct ip_hashmap_node_t *data = get_ipdata_by_hashmap(ip_address);
|
||||
const s64 current_time_sec = ktime_get_real_seconds();
|
||||
|
||||
if (data == NULL) {
|
||||
struct ip_hashmap_info info;
|
||||
info.ip_address_key = ip_address;
|
||||
info.ip_meta_info.last_attack_time = current_time_sec;
|
||||
info.ip_meta_info.remove_time = current_time_sec + time_sec;
|
||||
info.ip_meta_info.is_attack = true;
|
||||
put_ipdata_by_hashmap(ip_address, &info);
|
||||
return;
|
||||
}
|
||||
data->info.ip_meta_info.last_attack_time = current_time_sec;
|
||||
data->info.ip_meta_info.remove_time = current_time_sec + time_sec;
|
||||
data->info.ip_meta_info.is_attack = true;
|
||||
}
|
||||
bool check_is_blacklist_ip(size_t ip_address) {
|
||||
struct ip_hashmap_node_t *data = get_ipdata_by_hashmap(ip_address);
|
||||
if (data == NULL) {
|
||||
printk(KERN_ERR "Failed to get ip data from hashmap\n");
|
||||
return false;
|
||||
}
|
||||
return data->info.ip_meta_info.is_attack;
|
||||
}
|
||||
bool check_syn_attack(struct iphdr *ip_header, struct sk_buff *skb) {
|
||||
bool is_block = false;
|
||||
do {
|
||||
if (ip_header->protocol != IPPROTO_TCP) {
|
||||
break;
|
||||
}
|
||||
struct tcphdr *tcp_header = tcp_hdr(skb);
|
||||
if (tcp_header == NULL) {
|
||||
break;
|
||||
}
|
||||
if (tcp_header->syn == 0 || tcp_header->ack || tcp_header->rst) {
|
||||
break;
|
||||
}
|
||||
size_t ip_address_key = ip_header->saddr;
|
||||
struct ip_hashmap_node_t *data = get_ipdata_by_hashmap(ip_address_key);
|
||||
const s64 current_time_sec = ktime_get_real_seconds();
|
||||
if (data == NULL) {
|
||||
struct ip_hashmap_info info;
|
||||
info.ip_address_key = ip_address_key;
|
||||
info.syn_scan_info.last_seen = current_time_sec;
|
||||
info.syn_scan_info.num_syn_packets = 1;
|
||||
put_ipdata_by_hashmap(ip_address_key, &info);
|
||||
break;
|
||||
}
|
||||
s64 time_diff = current_time_sec - data->info.syn_scan_info.last_seen;
|
||||
if (time_diff >= SYN_SCAN_TIME) {
|
||||
data->info.syn_scan_info.num_syn_packets = 0;
|
||||
data->info.syn_scan_info.last_seen = current_time_sec;
|
||||
break;
|
||||
}
|
||||
data->info.syn_scan_info.num_syn_packets++;
|
||||
if (data->info.syn_scan_info.num_syn_packets >= SYN_SCAN_THRESHOLD) {
|
||||
// printk(KERN_ERR "SYN attack detected from %pI4 num packet: %d
|
||||
// \n",
|
||||
// &ip_header->saddr,
|
||||
// data->info.syn_scan_info.num_syn_packets);
|
||||
push_msg_syn_attack(ip_address_key);
|
||||
block_ip_address(ip_address_key, IP_ATTCK_BLOCK_TIME);
|
||||
is_block = true;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
return is_block;
|
||||
}
|
||||
|
||||
bool check_ssh_brute_force_attack(struct iphdr *ip_header,
|
||||
struct sk_buff *skb) {
|
||||
bool is_block = false;
|
||||
do {
|
||||
if (ip_header->protocol != IPPROTO_TCP) {
|
||||
break;
|
||||
}
|
||||
struct tcphdr *tcp_header = tcp_hdr(skb);
|
||||
if (tcp_header == NULL) {
|
||||
break;
|
||||
}
|
||||
if ((tcp_header->syn == 1) && (tcp_header->ack == 0)) {
|
||||
break;
|
||||
}
|
||||
// check port
|
||||
if (ntohs(tcp_header->dest) != SSH_PORT) {
|
||||
break;
|
||||
}
|
||||
size_t ip_address_key = ip_header->saddr;
|
||||
struct ip_hashmap_node_t *data = get_ipdata_by_hashmap(ip_address_key);
|
||||
const s64 current_time_sec = ktime_get_real_seconds();
|
||||
if (data == NULL) {
|
||||
struct ip_hashmap_info info;
|
||||
info.ip_address_key = ip_address_key;
|
||||
info.crack_ip_info.last_seen = current_time_sec;
|
||||
info.crack_ip_info.num_connect = 1;
|
||||
put_ipdata_by_hashmap(ip_address_key, &info);
|
||||
break;
|
||||
}
|
||||
s64 time_diff = current_time_sec - data->info.crack_ip_info.last_seen;
|
||||
if (time_diff >= SSH_BRUTE_FORCE_TIME) {
|
||||
data->info.crack_ip_info.num_connect = 0;
|
||||
data->info.crack_ip_info.last_seen = current_time_sec;
|
||||
break;
|
||||
}
|
||||
data->info.crack_ip_info.num_connect++;
|
||||
if (data->info.crack_ip_info.num_connect >= SSH_BRUTE_FORCE_THRESHOLD) {
|
||||
// printk(KERN_ERR "SYN attack detected from %pI4 num packet: %d
|
||||
// \n",
|
||||
// &ip_header->saddr,
|
||||
// data->info.syn_scan_info.num_syn_packets);
|
||||
push_msg_ssh_bf_attack(ip_address_key);
|
||||
block_ip_address(ip_address_key, IP_ATTCK_BLOCK_TIME);
|
||||
is_block = true;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
return is_block;
|
||||
}
|
||||
unsigned int network_callback(const struct nf_hook_ops *ops,
|
||||
struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *)) {
|
||||
bool is_block = false;
|
||||
do {
|
||||
if (skb == NULL) {
|
||||
break;
|
||||
}
|
||||
struct iphdr *ip_header = ip_hdr(skb);
|
||||
|
||||
if (ip_header == NULL) {
|
||||
break;
|
||||
}
|
||||
if (check_is_blacklist_ip(ip_header->saddr)) {
|
||||
is_block = true;
|
||||
printk(KERN_ERR "Block ip address: %pI4\n", &ip_header->saddr);
|
||||
break;
|
||||
}
|
||||
if (check_syn_attack(ip_header, skb)) {
|
||||
is_block = true;
|
||||
break;
|
||||
}
|
||||
if (check_ssh_brute_force_attack(ip_header, skb)) {
|
||||
is_block = true;
|
||||
break;
|
||||
}
|
||||
struct tcphdr *tcp_header = tcp_hdr(skb);
|
||||
if (tcp_header == NULL) {
|
||||
break;
|
||||
}
|
||||
if ((tcp_header->syn == 1) && (tcp_header->ack == 0)) {
|
||||
// push ip address to list
|
||||
push_msg_new_ip_connect(ip_header->saddr);
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
return is_block ? NF_DROP : NF_ACCEPT;
|
||||
}
|
||||
Reference in New Issue
Block a user