Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor mod slips #30

Merged
merged 11 commits into from
Nov 8, 2022
1 change: 1 addition & 0 deletions mod_slips/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ ADD requirements.txt /code/
RUN cd /StratosphereLinuxIPS/ && git checkout develop
RUN git pull
WORKDIR /code
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
CMD ["python3", "mod_slips.py"]
94 changes: 54 additions & 40 deletions mod_slips/mod_slips.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,62 @@
#!/usr/bin/env python3
# This file is part of the Civilsphere AI VPN
# See the file 'LICENSE' for copying permission.
# Author: Veronica Valeros, vero.valeros@gmail.com, veronica.valeros@aic.fel.cvut.cz
# Author: Veronica Valeros
# Contact: vero.valeros@gmail.com, veronica.valeros@aic.fel.cvut.cz

import os
import sys
import glob
import json
import redis
import logging
import subprocess
import configparser
from common.database import *
from collections import Counter
from common.database import redis_connect_to_db
from common.database import redis_create_subscriber
from common.database import redis_subscribe_to_channel


def process_profile_traffic(profile_name, PATH):
"""
Process the traffic for a given profile with Slips IDS.
"""

def process_profile_traffic(profile_name,PATH):
""" Function to process the traffic for a given profile. """
VALID_CAPTURE = False
try:
# Find all pcaps for the profile and process them
# Go to profile directory
os.chdir(f'{PATH}/{profile_name}')

# Find all pcaps for the profile and process them
for capture_file in glob.glob("*.pcap"):
os.mkdir(f'{PATH}/{profile_name}/slips_{capture_file}')
# Check size of packet capture
capture_size = os.stat(capture_file).st_size
logging.info(f'Processing capture {capture_file} ({capture_size} b)')

# If capture is not empty: process it
if capture_size > 25:
VALID_CAPTURE=True
# Run Slips here
OUTPUT=f'{PATH}/{profile_name}/slips_{capture_file}/'
FILENAME=f'{PATH}/{profile_name}/{capture_file}'
CONFIGURATION='/StratosphereLinuxIPS/aivpn_slips.conf'
args=['/StratosphereLinuxIPS/slips.py','-c',CONFIGURATION,'-f',FILENAME,'-o',OUTPUT]
process = subprocess.Popen(args,cwd="/StratosphereLinuxIPS", stdout=subprocess.PIPE)
process.wait()
return VALID_CAPTURE
return False
logging.info(f'Processing file: {capture_file} ({capture_size} b)')

# If capture is empty: do not process it
if capture_size < 26:
return False

# If capture is not empty, process it with Slips IDS
FILENAME = f'{PATH}/{profile_name}/{capture_file}'
SLIPS_OUTPUT = f'{PATH}/{profile_name}/slips_{capture_file}/'
SLIPS_CONF = '/StratosphereLinuxIPS/aivpn_slips.conf'

# Create Slips working directory
os.mkdir(f'{PATH}/{profile_name}/slips_{capture_file}')

# Run Slips as subprocess
args = ['/StratosphereLinuxIPS/slips.py', '-c', SLIPS_CONF,
'-f', FILENAME, '-o', SLIPS_OUTPUT]
process = subprocess.run(args, cwd="/StratosphereLinuxIPS",
stdout=subprocess.PIPE, timeout=86400)

# When all captures are processed, return True
return True
except Exception as err:
logging.info(f'Exception in process_profile_traffic: {err}')
return False


if __name__ == '__main__':
#Read configuration
# Read configuration
config = configparser.ConfigParser()
config.read('config/config.ini')

Expand All @@ -52,13 +65,14 @@ def process_profile_traffic(profile_name,PATH):
LOG_FILE = config['LOGS']['LOG_SLIPS']
PATH = config['STORAGE']['PATH']

logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG,format='%(asctime)s, MOD_SLIPS, %(message)s')
logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG,
format='%(asctime)s, MOD_SLIPS, %(message)s')

# Connecting to the Redis database
try:
redis_client = redis_connect_to_db(REDIS_SERVER)
except Exception as err:
logging.error(f'Unable to connect to the Redis database ({REDIS_SERVER}): {err}')
logging.error(f'Cannot connect to Redis ({REDIS_SERVER}): {err}')
sys.exit(-1)

# Creating a Redis subscriber
Expand All @@ -70,43 +84,43 @@ def process_profile_traffic(profile_name,PATH):

# Subscribing to Redis channel
try:
redis_subscribe_to_channel(db_subscriber,CHANNEL)
redis_subscribe_to_channel(db_subscriber, CHANNEL)
except Exception as err:
logging.error(f'Channel subscription failed: {err}')
sys.exit(-1)

# Starting Slips Redis Database
try:
# Run redis
subprocess.Popen(['redis-server','--daemonize','yes'])
subprocess.Popen(['redis-server', '--daemonize', 'yes'])
except Exception as err:
logging.error(f'Cannot Slips redis database: {err}')
sys.exit(-1)

try:
logging.info("Connection and channel subscription to redis successful.")
logging.info("Successful Redis connection and subscription.")

# Checking for messages
for item in db_subscriber.listen():
if item['type'] == 'message':
logging.info("New message received in channel {}: {}".format(item['channel'],item['data']))
logging.info(f"New message in channel {item['channel']}: {item['data']}")
if item['data'] == 'report_status':
redis_client.publish('services_status', 'MOD_SLIPS:online')
logging.info('MOD_SLIPS:online')
elif 'process_profile' in item['data']:
profile_name = item['data'].split(':')[1]
logging.info(f'Processing profile {profile_name} with Slips')
status = process_profile_traffic(profile_name,PATH)
logging.info(f'Status of the processing of profile {profile_name}: {status}')
logging.info(f'Running Slips on profile {profile_name}')
status = process_profile_traffic(profile_name, PATH)
logging.info(f'Slips analysis on {profile_name}: {status}')
if not status:
logging.info('An error occurred processing the capture with Slips')
message=f'slips_false:{profile_name}'
redis_client.publish('slips_processing',message)
logging.info('Error running Slips on profile')
message = f'slips_false:{profile_name}'
redis_client.publish('slips_processing', message)
continue
if status:
logging.info('Processing of associated captures completed')
message=f'slips_true:{profile_name}'
redis_client.publish('slips_processing',message)
logging.info('Slips analysis completed')
message = f'slips_true:{profile_name}'
redis_client.publish('slips_processing', message)

redis_client.publish('services_status', 'MOD_SLIPS:offline')
logging.info("Terminating")
Expand Down
1 change: 0 additions & 1 deletion mod_slips/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
redis
psutil
2 changes: 1 addition & 1 deletion mod_slips/slips_configuration.conf
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ create_log_files = yes
delete_zeek_files = no

# Store zeek files in the output dir. Only yes or no
store_a_copy_of_zeek_files = no
store_a_copy_of_zeek_files = yes

# Create a metadata dir output/metadata/ that has a copy of slips.conf, whitelist file, current commit and date
# available options are yes or no
Expand Down