Skip to content
Snippets Groups Projects
Commit 44884958 authored by NGUYEN Do Duc Anh's avatar NGUYEN Do Duc Anh
Browse files

add opportunistic function to node and monitor

parent 46c22edf
Branches
No related tags found
No related merge requests found
import subprocess
from netfilterqueue import NetfilterQueue
from opportunistic_utils import *
map_IP_with_source_switch = {}
def process_packet(new_packet):
data = new_packet.get_payload()
# Parse the raw data into a Scapy IP packet
pkt = IP(data)
if pkt.haslayer(IP):
print(f"IP Packet: {pkt.summary()}")
pkt.show()
index_custom_option = -1
if pkt.options:
for i in range(len(pkt.options)):
option = pkt.options[i]
if isinstance(option, CustomIPOption) and option.option == MY_OPTION_TYPE:
index_custom_option = i
for entry in option.read_all_entry():
# save ip address for later attacker, node_id and interface_num
if entry["cmd"] == Cmd.REGISTER:
print(f"Custom Option from REGISTER found: id = {entry['node_id']}, inter = vmnet{entry['inter_num']}")
map_IP_with_source_switch[pkt[IP].src] = {"node_id": entry['node_id'], "inter_num": entry['inter_num']}
IP_attacker = "172.16.60.133"
if pkt[IP].dst == IP_attacker and IP_attacker in map_IP_with_source_switch:
info = map_IP_with_source_switch[IP_attacker]
node_id = info["node_id"]
inter_num = info["inter_num"]
if index_custom_option == -1:
option = CustomIPOption()
option.add_entry(node_id, inter_num, Cmd.DECISION_DROP)
if pkt.options:
pkt.options.append(option) # Append to the existing options
else:
pkt.options = [option] # Add as the first option if none exist
else:
pkt.options[index_custom_option].add_entry(node_id, inter_num, Cmd.DECISION_DROP)
del pkt[IP].chksum # Invalidate the checksum
new_packet.set_payload(bytes(pkt))
pkt.show()
new_packet.accept()
def main():
check_rule_command = "sudo iptables -C FORWARD -p tcp -j NFQUEUE --queue-num 1"
try:
# Run the check command
subprocess.run(check_rule_command, shell=True, check=True)
print("Rule already exists, no need to add it.")
except subprocess.CalledProcessError:
# If the rule doesn't exist, add it
add_rule_command = "sudo iptables -I FORWARD -p tcp -j NFQUEUE --queue-num 1"
try:
subprocess.run(add_rule_command, shell=True, check=True)
print("Rule added successfully.")
except subprocess.CalledProcessError as e:
print(f"Failed to add the rule: {e}")
q = NetfilterQueue()
q.bind(1, process_packet) # Bind to queue number 1
try:
# Run the queue listener
print("Listening for packets...")
q.run()
except KeyboardInterrupt:
print("Stopping packet listener")
if __name__ == "__main__":
main()
import subprocess
from netfilterqueue import NetfilterQueue
from opportunistic_utils import *
debug = True
name_interface = "vmnet" if debug else "ens"
MIN_INTER_NUMBER = 1 if debug else 4
MAX_INTER_NUMBER = 2 if debug else 14
MARK_TO_INTERFACE = {}
for index in range(MIN_INTER_NUMBER, MAX_INTER_NUMBER):
MARK_TO_INTERFACE[index] = name_interface + str(index)
my_id = 1
def process_packet(new_packet):
global my_id
inter_num = new_packet.get_mark()
# Determine the incoming interface based on the mark
interface = MARK_TO_INTERFACE.get(inter_num, 'unknown')
print(interface)
data = new_packet.get_payload()
# Parse the raw data into a Scapy IP packet
pkt = IP(data)
# Check if it's a TCP packet
if pkt.haslayer(IP):
print(f"IP Packet: {pkt.summary()}")
pkt.show()
is_register_me = True
index_custom_option = -1
if pkt.options:
for i in range(len(pkt.options)):
option = pkt.options[i]
if isinstance(option, CustomIPOption) and option.option == MY_OPTION_TYPE:
index_custom_option = i
for entry in option.read_all_entry():
if entry["cmd"] == Cmd.DECISION_DROP:
print(
f"Custom Option from DECISION found: id = {entry['node_id']}, inter = vmnet{entry['inter_num']}, cmd = {entry['cmd']}")
# Do something to deploy firewall
elif entry["cmd"] == Cmd.REGISTER:
is_register_me = False
if is_register_me:
if index_custom_option == -1:
option = CustomIPOption()
option.add_entry(my_id, inter_num, Cmd.REGISTER)
if pkt.options:
pkt.options.append(option) # Append to the existing options
else:
pkt.options = [option] # Add as the first option if none exist
else:
pkt.options[index_custom_option].add_entry(my_id, inter_num, Cmd.REGISTER)
del pkt[IP].chksum # Invalidate the checksum
new_packet.set_payload(bytes(pkt))
pkt.show() # Now this will work correctly
new_packet.accept()
def main():
for i in range(MIN_INTER_NUMBER, MAX_INTER_NUMBER):
inter_name = MARK_TO_INTERFACE[i]
rule_1 = f"sudo iptables -t mangle -A PREROUTING -i {inter_name} -j MARK --set-mark {i}"
rule_check = "sudo iptables -C FORWARD -p tcp -j NFQUEUE --queue-num 1"
rule_2 = "sudo iptables -I FORWARD -p tcp -j NFQUEUE --queue-num 1"
try:
subprocess.run(rule_check, shell=True, check=True)
print("Rule already exists, no need to add it.")
except subprocess.CalledProcessError:
try:
subprocess.run(rule_1, shell=True, check=True)
subprocess.run(rule_2, shell=True, check=True)
print("Rule added successfully.")
except subprocess.CalledProcessError as e:
print(f"Failed to add the rule: {e}")
q = NetfilterQueue()
q.bind(1, process_packet) # Bind to queue number 1
try:
# Run the queue listener
print("Listening for packets...")
q.run()
except KeyboardInterrupt:
print("Stopping packet listener")
if __name__ == "__main__":
main()
from scapy.all import *
from scapy.layers.inet import IPOption, IP
MY_OPTION_TYPE = 31
class Cmd:
DECISION_DROP = 0
REGISTER = 1
class CustomIPOption(IPOption):
name = "CustomIPOption"
fields_desc = [
ByteField("option", MY_OPTION_TYPE), # Option type
FieldLenField("length", 3, length_of="value", fmt="B"), # Option length
ByteField("count", 0), # Number of entries in the array
StrLenField("value", "", length_from=lambda pkt: pkt.length - 3), # Array data (id, inter, cmd)
]
# Custom methods to add entries (id, inter, cmd) to the value field
def add_entry(self, id_val, inter_val, cmd_val):
entry = struct.pack('!IBB', id_val, inter_val, cmd_val)
self.value += entry
self.count += 1 # Update the count field
self.length += len(entry)
# Custom method to read a specific entry by index
def read_entry(self, index):
if index < self.count:
# Calculate the offset of the entry in the value field
offset = index * 12 # Each entry is 12 bytes (3 integers)
entry_data = self.value[offset:offset + 12]
id_val, inter_val, cmd_val = struct.unpack('!IBB', entry_data)
return {"node_id": id_val, "inter_num": inter_val, "cmd": cmd_val}
else:
raise IndexError("Entry index out of range")
# Custom method to read all entries at once
def read_all_entry(self):
entries = []
for i in range(self.count):
entry = self.read_entry(i)
entries.append(entry)
return entries
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment