diff --git a/ChangeLog b/ChangeLog index 251dbf50115ca99f9f181c2716af32d8334b4254..8d9bf148bfc0b20210411594dc3f24f88421c17e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +======= +1.8.2 RELEASE (2024/06) +Improvements and enhancements + - Introduced separate mitigation statistics for matched vs. dropped packets/bytes (JUNOS-specific use of firewall MIB for mitigation statistics) + ======= 1.8.1 RELEASE (2023/11) Improvements and enhancements diff --git a/_version.py b/_version.py index 5f1f864f974daae2330d22721f0b15da4a1b6c7e..960fa5453de901419788eddab969a8948e0423b4 100644 --- a/_version.py +++ b/_version.py @@ -1,6 +1,7 @@ #VERSION = '1.5' #VERSION = '1.8.0' -VERSION = '1.8.1' +#VERSION = '1.8.1' +VERSION = '1.8.2' if __name__ == "__main__": print(VERSION) diff --git a/flowspec/models.py b/flowspec/models.py index a81a9655281727826bf953458404d90ed781985e..19fc67bf09789a7a704be1d6cc3f8b1f75054bfa 100644 --- a/flowspec/models.py +++ b/flowspec/models.py @@ -213,6 +213,13 @@ class Route(models.Model): else: return None + def then_action1_string(self): + ret="" + for then_action in self.then.all(): + ret=str(then_action) + return ret + return ret + def ip_version(self): route_obj = self @@ -328,6 +335,31 @@ class Route(models.Model): def commit_edit(self, *args, **kwargs): peers = self.applier.userprofile.peers.all() + try: + last_then_str = kwargs['last__then_action__string'] + except: + last_then_str = "" + logger.info('last_then_str=%s' % last_then_str) + + new_then_str = self.then_action1_string() + logger.info('new_then_str=%s' % new_then_str) + + ## + + str_prefix="rate-limit:" + + last__rate_limit="" + if last_then_str[0:len(str_prefix)]==str_prefix: + last__rate_limit=last_then_str[len(str_prefix):] + logger.info('last__rate_limit=%s' % last__rate_limit) + + new__rate_limit="" + if new_then_str[0:len(str_prefix)]==str_prefix: + new__rate_limit=new_then_str[len(str_prefix):] + logger.info('new__rate_limit=%s' % new__rate_limit) + + rate_limit_changed = last__rate_limit != new__rate_limit + #username = None #for peer in peers: # if username: @@ -345,7 +377,7 @@ class Route(models.Model): peer = None send_message('[%s] Editing rule %s. Please wait...' % (self.applier_username_nice, self.name_visible), peer, self) - response = edit.delay(self.pk) + response = edit.delay(self.pk, rate_limit_changed=rate_limit_changed) logger.info('Got edit job id: %s' % response) if not settings.DISABLE_EMAIL_NOTIFICATION: fqdn = Site.objects.get_current().domain diff --git a/flowspec/snmpstats.py b/flowspec/snmpstats.py index c0a3845d701b885cf5f981168f8c69f1dea40ef1..79c5cb514bd23f2318421cc8dcc44033689ec151 100644 --- a/flowspec/snmpstats.py +++ b/flowspec/snmpstats.py @@ -456,17 +456,52 @@ def poll_snmp_statistics(): try: if xtype==xtype_default: logger.info("poll_snmp_statistics(): 1a STATISTICS_PER_RULE rule_id="+str(rule_id)) - counter = {"ts": nowstr, "value": newdata[flowspec_params_str][xtype_default]} + val_dropped = newdata[flowspec_params_str][xtype_default] + counter = {"ts": nowstr, "value": val_dropped} else: logger.info("poll_snmp_statistics(): 1b STATISTICS_PER_RULE rule_id="+str(rule_id)) + try: val_dropped = newdata[flowspec_params_str][xtype_default] except Exception: val_dropped = 1 + try: val_matched = newdata[flowspec_params_str][xtype] + + logger.info("poll_snmp_statistics(): 1b STATISTICS_PER_RULE rule_id="+str(rule_id)+" before last_matched__remember_offset_value fix: val_matched="+str(val_matched)) + + ## + + val_matched__pkts = newdata[flowspec_params_str][xtype]["packets"] + val_matched__bytes = newdata[flowspec_params_str][xtype]["bytes"] + + key_remember_oldmatched = str(rule_id)+".remember_oldmatched_offset" + try: + last_matched__remember_offset_value = history_per_rule[key_remember_oldmatched]["value_matched"] + logger.info("poll_snmp_statistics(): 1b STATISTICS_PER_RULE rule_id="+str(rule_id)+" before last_matched__remember_offset_value fix: last_matched__remember_offset_value="+str(last_matched__remember_offset_value)) + + last_matched__remember_offset_value__pkts = last_matched__remember_offset_value["packets"] + last_matched__remember_offset_value__bytes = last_matched__remember_offset_value["bytes"] + except: + last_matched__remember_offset_value__pkts = 0 + last_matched__remember_offset_value__bytes = 0 + + val_matched__pkts = val_matched__pkts + last_matched__remember_offset_value__pkts + val_matched__bytes = val_matched__bytes + last_matched__remember_offset_value__bytes + + newdata[flowspec_params_str][xtype]["packets"] = val_matched__pkts + newdata[flowspec_params_str][xtype]["bytes"] = val_matched__bytes + + logger.info("poll_snmp_statistics(): 1b STATISTICS_PER_RULE rule_id="+str(rule_id)+" after last_matched__remember_offset_value fix: val_matched="+str(val_matched)) + + ## + except Exception: val_matched = 1 + + ## + counter = { "ts": nowstr, "value": val_dropped, "value_matched": val_matched } counter_is_null = False @@ -526,6 +561,7 @@ def poll_snmp_statistics(): elif not last_is_null and not rule_newer_than_last: logger.debug("poll_snmp_statistics(): STATISTICS_PER_RULE: rule_id="+str(rule_id)+" case existing active 00") rec.insert(0, counter) + history_per_rule[str(rule_id)+".last"] = counter history_per_rule[rule_id] = rec[:samplecount] except Exception as e: @@ -607,3 +643,112 @@ def add_initial_zero_value(rule_id, route_obj, zero_or_null=True): unlock_history_file() +## + +# workaround for rate limiting rules whose rate limit is changed while the rule is active -> old (absoluet) matched statistics value would be lost afterwards and not be counted as part of the future (absolute) matched statistics value; because the oid keys for the matched value (depending on the rate limit) in the SNMP table have changed +# +# to be called before the rule's rate-limit is changed on the router +# +# TODO; call this function on change of an active rate limit rule whose rate limit is changed: remember_oldmatched__for_changed_ratelimitrules_whileactive() +# TODO: on decativation of the rule the remembered matched value offset set in this function has to be cleared (add new function for this and call it appropriately): clean_oldmatched__for_changed_ratelimitrules_whileactive() +# TODO: use the remembered matched value offset in get_snmp_stats (add to matched value gathered from SNMP) +# + +def remember_oldmatched__for_changed_ratelimitrules_whileactive(rule_id, route_obj): + rule_id=str(rule_id) + logger.debug("remember_oldmatched__for_changed_ratelimitrules_whileactive(): rule_id="+str(rule_id)) + + # get new data + now = datetime.now() + nowstr = now.isoformat() + + key_last_measurement = str(rule_id)+".last" + key_remember_oldmatched = str(rule_id)+".remember_oldmatched_offset" + + # lock history file access + success = lock_history_file(wait=1, reason="remember_oldmatched__for_changed_ratelimitrules_whileactive("+str(rule_id)+")") + if not success: + logger.error("remember_oldmatched__for_changed_ratelimitrules_whileactive(): locking history file failed, aborting"); + return False + + # load history + history = load_history() + + try: + history_per_rule = history['_per_rule'] + except Exception as e: + history_per_rule = {} + + try: + last_matched__measurement_value = history_per_rule[key_last_measurement]["value_matched"] + last_matched__measurement_value__pkts = last_matched__measurement_value["packets"] + last_matched__measurement_value__bytes = last_matched__measurement_value["bytes"] + except: + last_matched__measurement_value__pkts = 0 + last_matched__measurement_value__bytes = 0 + + try: + last_matched__remember_offset_value = history_per_rule[key_remember_oldmatched]["value_matched"] + last_matched__remember_offset_value__pkts = last_matched__remember_offset_value["packets"] + last_matched__remember_offset_value__bytes = last_matched__remember_offset_value["bytes"] + except: + last_matched__remember_offset_value__pkts = 0 + last_matched__remember_offset_value__bytes = 0 + + # + + #logger.info("remember_oldmatched__for_changed_ratelimitrules_whileactive(): last_matched__measurement_value="+str(last_matched__measurement_value)+" last_matched__remember_offset_value="+str(last_matched__remember_offset_value)); + + last_matched__remember_offset_value__pkts = last_matched__remember_offset_value__pkts + last_matched__measurement_value__pkts + last_matched__remember_offset_value__bytes = last_matched__remember_offset_value__bytes + last_matched__measurement_value__bytes + + counter = { "ts": nowstr, "value_matched": { "packets" : last_matched__remember_offset_value__pkts, "bytes" : last_matched__remember_offset_value__bytes } } + + try: + history_per_rule[key_remember_oldmatched] = counter + + history['_per_rule'] = history_per_rule + + # store updated history + save_history(history, nowstr) + + except Exception as e: + logger.error("remember_oldmatched__for_changed_ratelimitrules_whileactive(): failure: exception: "+str(e)) + + unlock_history_file() + + +def clean_oldmatched__for_changed_ratelimitrules_whileactive(rule_id, route_obj): + rule_id=str(rule_id) + logger.debug("clean_oldmatched__for_changed_ratelimitrules_whileactive(): rule_id="+str(rule_id)) + + key_remember_oldmatched = str(rule_id)+".remember_oldmatched_offset" + + # lock history file access + success = lock_history_file(wait=1, reason="clean_oldmatched__for_changed_ratelimitrules_whileactive("+str(rule_id)+","+str(zero_or_null)+")") + if not success: + logger.error("clean_oldmatched__for_changed_ratelimitrules_whileactive(): locking history file failed, aborting"); + return False + + # load history + history = load_history() + + try: + history_per_rule = history['_per_rule'] + except Exception as e: + history_per_rule = {} + + try: + history_per_rule[key_remember_oldmatched] = {} + + history['_per_rule'] = history_per_rule + + # store updated history + save_history(history, nowstr) + + except Exception as e: + logger.error("clean_oldmatched__for_changed_ratelimitrules_whileactive(): failure: exception: "+str(e)) + + unlock_history_file() + + diff --git a/flowspec/tasks.py b/flowspec/tasks.py index 7947c3079b4c040f2c8e313ad35fbf1e0e32675b..dba7c2f1d29750e4c36335adc150824bff278296 100644 --- a/flowspec/tasks.py +++ b/flowspec/tasks.py @@ -55,7 +55,7 @@ def add(routepk, callback=None): route.response = response route.save() #snmp_add_initial_zero_value.delay(str(route.id), True) - snmp_add_initial_zero_value(routepk, route.id, True) # route must exist, so that snmp_add_initial_zero_value can find it in DB + snmp_add_initial_zero_value(routepk, route.id, add_initial_value=True, zero_or_null=True, reset_remember_last_value=True, update_remember_last_value=False) # route must exist, so that snmp_add_initial_zero_value can find it in DB elif response=="Task timeout": if deactivate_route.request.retries < settings.NETCONF_MAX_RETRY_BEFORE_ERROR: # repeat the action @@ -71,21 +71,29 @@ def add(routepk, callback=None): @shared_task(ignore_result=True, autoretry_for=(TimeLimitExceeded, SoftTimeLimitExceeded), retry_backoff=True, retry_kwargs={'max_retries': settings.NETCONF_MAX_RETRY_BEFORE_ERROR}) -def edit(routepk, callback=None): +def edit(routepk, rate_limit_changed=False, callback=None): from flowspec.models import Route route = Route.objects.get(pk=routepk) status_pre = route.status logger.info("tasks::edit(): routepk="+str(routepk)+" => route="+str(route)+", status_pre="+str(status_pre)) + + logger.info("tasks::edit(): rate_limit_changed="+str(rate_limit_changed)) + applier = PR.Applier(route_object=route) commit, response = applier.apply(operation="replace") if commit: route.status = "ACTIVE" route.response = response route.save() # save() has to be called before snmp_add_initial_zero_value, as last_updated DB filed is updated now on every call of save() and last db_measurement time must become >= this new last_updated value - if False: # actually wrong to use it for an edited active rule, as the stats values do not drop to zero on the JUNOS router + + update_remember_last_value = rate_limit_changed + + if update_remember_last_value: + # actually wrong to use add_initial_zero_value=True for an edited active rule, as the stats values do not drop to zero on the JUNOS router try: #snmp_add_initial_zero_value.delay(str(route.id), True) - snmp_add_initial_zero_value(routepk, route.id, True) + #snmp_add_initial_zero_value(routepk, route.id, True, True, True) + snmp_add_initial_zero_value(routepk, route.id, add_initial_value=False, zero_or_null=True, reset_remember_last_value=False, update_remember_last_value=True) except Exception as e: logger.error("tasks::edit(): route="+str(route)+", ACTIVE, add_initial_zero_value failed: "+str(e)) elif response=="Task timeout": @@ -131,7 +139,7 @@ def deactivate_route(routepk, **kwargs): if commit: route.status="INACTIVE" try: - snmp_add_initial_zero_value(routepk, route.id, False) + snmp_add_initial_zero_value(routepk, route.id, add_initial_value=True, zero_or_null=False, reset_remember_last_value=True, update_remember_last_value=False) except Exception as e: logger.error("tasks::deactivate_route(): route="+str(route)+", INACTIVE, add_null_value failed: "+str(e)) @@ -442,10 +450,39 @@ def poll_snmp_statistics(): os._exit(0) logger.info("poll_snmp_statistics(): after os._exit() in child process (pid="+str(pid)+", ppid="+str(ppid)+")") +## + +def snmp_add_initial_zero_value_inner(routepk, route_id, route, snmpstats, add_initial_value=True, zero_or_null=True, reset_remember_last_value=True, update_remember_last_value=False): + + logger.info("snmp_add_initial_zero_value_inner(): called: routepk="+str(routepk)+" route_id="+str(route_id)+" add_initial_value="+str(add_initial_value)+" zero_or_null="+str(zero_or_null)+" reset_remember_last_value="+str(reset_remember_last_value)+" update_remember_last_value="+str(update_remember_last_value)) + + if add_initial_value: + try: + snmpstats.add_initial_zero_value(route_id, route, zero_or_null) + logger.debug("snmp_add_initial_zero_value_inner(): (1) routepk="+str(routepk)+","+str(zero_or_null)+" add_initial_zero_value sucesss") + except Exception as e: + logger.error("snmp_add_initial_zero_value_inner(): (1) routepk="+str(routepk)+","+str(zero_or_null)+" add_initial_zero_value failed: "+str(e)) + + if reset_remember_last_value: + try: + snmpstats.clean_oldmatched__for_changed_ratelimitrules_whileactive(route_id, route) + logger.debug("snmp_add_initial_zero_value_inner(): (2) routepk="+str(routepk)+","+str(zero_or_null)+" clean_oldmatched__for_changed_ratelimitrules_whileactive sucesss") + except Exception as e: + logger.error("snmp_add_initial_zero_value_inner(): (2) routepk="+str(routepk)+","+str(zero_or_null)+" clean_oldmatched__for_changed_ratelimitrules_whileactive failed: "+str(e)) + + elif update_remember_last_value: + try: + logger.info("snmp_add_initial_zero_value_inner(): (3a) routepk="+str(routepk)+" route_id="+str(route_id)+" add_initial_value="+str(add_initial_value)+" zero_or_null="+str(zero_or_null)+" reset_remember_last_value="+str(reset_remember_last_value)+" update_remember_last_value="+str(update_remember_last_value)) + snmpstats.remember_oldmatched__for_changed_ratelimitrules_whileactive(route_id, route) + logger.info("snmp_add_initial_zero_value_inner(): (3b) routepk="+str(routepk)+","+str(zero_or_null)+" remember_oldmatched__for_changed_ratelimitrules_whileactive sucesss") + except Exception as e: + logger.error("snmp_add_initial_zero_value_inner(): (4) routepk="+str(routepk)+","+str(zero_or_null)+" remember_oldmatched__for_changed_ratelimitrules_whileactive failed: "+str(e)) + + @shared_task(ignore_result=True, max_retries=0) -def snmp_add_initial_zero_value(routepk, route_id, zero_or_null=True): +def snmp_add_initial_zero_value(routepk, route_id, add_initial_value=True, zero_or_null=True, reset_remember_last_value=True, update_remember_last_value=False): from flowspec import snmpstats - logger.info("snmp_add_initial_zero_value(): routepk="+str(routepk)+" route_id="+str(route_id)) + logger.info("snmp_add_initial_zero_value(): routepk="+str(routepk)+" route_id="+str(route_id)+" add_initial_value="+str(add_initial_value)+" zero_or_null="+str(zero_or_null)+" reset_remember_last_value="+str(reset_remember_last_value)+" update_remember_last_value="+str(update_remember_last_value)) route = None if route==None: @@ -459,7 +496,9 @@ def snmp_add_initial_zero_value(routepk, route_id, zero_or_null=True): use_fork = False if not use_fork: - snmpstats.add_initial_zero_value(route_id, route, zero_or_null) + + snmp_add_initial_zero_value_inner(routepk, route_id, route, snmpstats, add_initial_value=add_initial_value, zero_or_null=zero_or_null, reset_remember_last_value=reset_remember_last_value, update_remember_last_value=update_remember_last_value) + else: signal.signal(signal.SIGCHLD, handleSIGCHLD) @@ -474,12 +513,8 @@ def snmp_add_initial_zero_value(routepk, route_id, zero_or_null=True): ppid = pid pid = os.getpid() logger.info("snmp_add_initial_zero_value(): in child process (pid="+str(pid)+", ppid="+str(ppid)+")") - - try: - snmpstats.add_initial_zero_value(route_id, route, zero_or_null) - logger.debug("snmp_add_initial_zero_value(): routepk="+str(routepk)+","+str(zero_or_null)+" sucesss") - except Exception as e: - logger.error("snmp_add_initial_zero_value(): routepk="+str(routepk)+","+str(zero_or_null)+" failed: "+str(e)) + + snmp_add_initial_zero_value_inner(routepk, route_id, route, snmpstats, add_initial_value=add_initial_value, zero_or_null=zero_or_null, reset_remember_last_value=reset_remember_last_value, update_remember_last_value=update_remember_last_value) #exit_process() diff --git a/flowspec/views.py b/flowspec/views.py index 9482dac9512b9b47c697e0a87e0649c27e2a102b..20c4a5e227761fa7c1c94305cd56f6a8e57de386 100644 --- a/flowspec/views.py +++ b/flowspec/views.py @@ -482,6 +482,10 @@ def edit_route(request, route_slug): ) return HttpResponseRedirect(reverse("group-routes")) route_original = deepcopy(route_edit) + + last__then_action__string = route_original.then_action1_string() + logger.info("views::edit(): debug: pre pre route.then1="+last__then_action__string) + if request.POST: request_data = request.POST.copy() if request.user.is_superuser: @@ -569,7 +573,22 @@ def edit_route(request, route_slug): route.save() if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'): form.save_m2m() - route.commit_edit() + + #logger.info("views::edit(): debug: pre route.then.all()="+str(route_original.then.all())) + #str_prefix="rate-limit:" + #rate_limit="" + #for then_action in route_original.then.all(): + # logger.info("views::edit(): pre debug: str="+str(then_action)) + # logger.info("views::edit(): pre debug: str="+str(then_action)[0:len(str_prefix)]) + # if str(then_action)[0:len(str_prefix)]==str_prefix: + # logger.info("views::edit(): pre debug: rate-limit") + # rate_limit=str(then_action)[len(str_prefix)+1:] + #logger.info("views::edit(): debug: pre after loop") + #last__then_action__string = route_original.then_action1_string() + logger.info("views::edit(): debug: pre pre route.then1="+last__then_action__string) + + route.commit_edit(last__then_action__string=last__then_action__string) + return HttpResponseRedirect(reverse("group-routes")) else: if not request.user.is_superuser: diff --git a/inst/testing/nemo1/install_and_run_vsmd b/inst/testing/nemo1/install_and_run_vsmd new file mode 100755 index 0000000000000000000000000000000000000000..482aa9ac1a8f340220beed085f249455c1b0ee26 --- /dev/null +++ b/inst/testing/nemo1/install_and_run_vsmd @@ -0,0 +1,67 @@ +#!/bin/bash + +if [ ! -f /.nemo_vsmd_setuped ]; then + + set -e + + apt-get -yyy install xtables-addons-dkms xtables-addons-common exabgp linux-headers-amd64 + + export PERL_MM_USE_DEFAULT=1 + + perl -MCPAN -e 'install (Net::CIDR::Lite)' + perl -MCPAN -e 'install (Text::CSV_XS)' + mkdir -p /usr/share/xt_geoip + + ( + cd /usr/share/xt_geoip + /usr/libexec/xtables-addons/xt_geoip_dl + /usr/libexec/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip + ) + + apt-get -yyy install virtualenv + + touch /.nemo_vsmd_setuped + +fi + +# + +cd nemo-vsmd/ + +if [ ! -d venv ]; then + virtualenv venv +fi + +. venv/bin/activate + +pip install -r requirements.txt + +export PYTHONPATH="$PYTHONPATH:$PWD/lib/python3/" + +mkdir -p /services/etc/nemo/ + +if [ ! -f /services/etc/nemo/nemo.conf -o ../nemo.conf.vsmd -nt /services/etc/nemo/nemo.conf ]; then + #touch /services/etc/nemo/nemo.conf + #echo "[vsmd]" >> /services/etc/nemo/nemo.conf + # + #cp -vf ./doc/nemo.conf.example /services/etc/nemo/nemo.conf + # + cp -vf ../nemo.conf.vsmd /services/etc/nemo/nemo.conf +fi + +if [ ! -f /services/data/vsmd/vsmd.sqlite ]; then + mkdir -p /services/data/vsmd/ + touch /services/data/vsmd/vsmd.sqlite +fi + +echo TODO: configure /services/etc/nemo/nemo.conf +echo use ./bin/adm.py OR ./bin/nemo-vsmd + +if [ "$1" = "--install_only" ]; then + echo "use ./bin/nemo-vsmd to run inside outer container" +else + exec ./bin/nemo-vsmd "$@" +fi + + + diff --git a/inst/testing/nemo1/mynemo-docker-dind b/inst/testing/nemo1/mynemo-docker-dind index 29ce1625e238646e5f54f5847fedf774fa875b85..287a4cd68ab366d38db6889a4524be662941b756 100755 --- a/inst/testing/nemo1/mynemo-docker-dind +++ b/inst/testing/nemo1/mynemo-docker-dind @@ -64,13 +64,22 @@ fi #xarg ./mynemo-docker-dind --freertr-host2-ping-host1 # enter host2 container and run ping host1 #xarg ./mynemo-docker-dind --freertr-tshark-netconf # enter freertr container and run tshark on eth3, in order to monitor netconf traffic towards nemo container #xarg ./mynemo-docker-dind --nemo-tshark-netconf # enter (outer) nemo d-in-d container and run tshark on eth1, in order to monitor netconf traffic from freertr container -#xarg ./mynemo-docker-dind --nemo-get-filename-of-cerfile # show filename of client certificate filename (as seen from outside of outer nemo d-in-d container) +#xarg ./mynemo-docker-dind --nemo-get-filename-of-certfile # show filename of client certificate filename (as seen from outside of outer nemo d-in-d container) +#xarg ./mynemo-docker-dind --nemo-get-dirname-onhost # show dirname of inside container dir /nemo-all/ as seen from outside on the host ## -docker_outer__docker_file_name="Dockerfile-nemo-all" docker_outer__image_name="nemo-all1" docker_outer__container_name="nemo-all1" +docker_outer_volume_forinnerdockerdir="dind1" + +outer_https_port="8000" + +docker_log_postfix="_1" # has to be consistent with docker_outer__container_name? + +# + +docker_outer__docker_file_name="Dockerfile-nemo-all" docker_outer_hostname="localhost" @@ -164,18 +173,18 @@ elif [ "$1" = "--docker-build" ]; then #arg ## #echo "# starting new debian-docker-in-docker container:" 1>&2 - #docker_outer__container_name="$(set -x; docker run --privileged --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume dind1:/var/lib/docker/ --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name" sh -c "ls -l /nemo-all; tree -d /nemo-all/")" + #docker_outer__container_name="$(set -x; docker run --privileged --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume "$docker_outer_volume_forinnerdockerdir:/var/lib/docker/" --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name" sh -c "ls -l /nemo-all; tree -d /nemo-all/")" #echo "docker_outer__image_name=$docker_outer__image_name" 1>&2 #echo 1>&2 #exit - #echo "# pruning outer volume dind1:" 1>&2 - #(set -x; docker volume rm dind1) + #echo "# pruning outer volume $docker_outer_volume_forinnerdockerdir:" 1>&2 + #(set -x; docker volume rm "$docker_outer_volume_forinnerdockerdir") outer_docker_space_dir="$(docker info | grep "Docker Root Dir:" | awk '{ print $(NF); }')" echo "# pruning inner containers before inner docker daemon is started (outer_docker_space_dir=$outer_docker_space_dir):" 1>&2 #(set -x; rm -rf /var/lib/docker/volumes/dind1/_data/containers/*) - (set -x; rm -rf "$outer_docker_space_dir/volumes/dind1/_data/containers/"*) || true + (set -x; rm -rf "$outer_docker_space_dir/volumes/$docker_outer_volume_forinnerdockerdir/_data/containers/"*) || true echo 1>&2 ## @@ -196,9 +205,9 @@ elif [ "$1" = "--docker-build" ]; then #arg ## echo "# starting new debian-docker-in-docker container:" 1>&2 - (set -x; docker run -d --privileged --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume dind1:/var/lib/docker/ --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name") - #(set -x; docker run -d --privileged --net dind-mgmt --net nemo-flow-input --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume dind1:/var/lib/docker/ --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name") - #(set -x; docker run -d --privileged --net dind-mgmt --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume dind1:/var/lib/docker/ --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name") + (set -x; docker run -d --privileged --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume "$docker_outer_volume_forinnerdockerdir:/var/lib/docker/" --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p "$outer_https_port:443" "$docker_outer__image_name") + #(set -x; docker run -d --privileged --net dind-mgmt --net nemo-flow-input --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume "$docker_outer_volume_forinnerdockerdir:/var/lib/docker/" --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name") + #(set -x; docker run -d --privileged --net dind-mgmt --volume "$SSH_AUTH_SOCK:/ssh-auth-sock" --volume "$docker_outer_volume_forinnerdockerdir:/var/lib/docker/" --hostname "$docker_outer_hostname" --name "$docker_outer__container_name" -t -p 8000:443 "$docker_outer__image_name") docker network connect "$network1_name" "$docker_outer__container_name" echo 1>&2 @@ -308,7 +317,8 @@ elif [ "$1" = "--setup" -o "$1" = "--run-setup-inside" ]; then #arg echo "# inside debian-docker-in-docker container: run setup.sh :" 1>&2 #(set -x; docker exec -ti "$docker_outer__container_name" bash -c 'export SSH_AUTH_SOCK="/ssh-auth-sock"; cd /nemo-all/nemo-docker && ./setup.sh --verbose "$@"' -- "$@") - (set -x; docker exec -ti "$docker_outer__container_name" bash -c 'export SSH_AUTH_SOCK="/ssh-auth-sock"; cd /nemo-all/nemo-docker && ./setup.sh "$@"' -- "$@") + #(set -x; docker exec -ti "$docker_outer__container_name" bash -c 'export SSH_AUTH_SOCK="/ssh-auth-sock"; cd /nemo-all/nemo-docker && ./setup.sh "$@"' -- "$@") + (set -x; docker exec -ti "$docker_outer__container_name" bash -c 'export SSH_AUTH_SOCK="/ssh-auth-sock"; export ADMIN_MAIL="test@localhost"; export ADMIN_NAME="test"; cd /nemo-all/nemo-docker && ./setup.sh "$@"' -- "$@") echo 1>&2 #echo "# inside debian-docker-in-docker container: test access to UI via curl (assumes empty password for the client certificate):" 1>&2 @@ -405,17 +415,17 @@ elif [ "$1" = "--docker.containerids" ]; then #arg elif [ "$1" = "--logs0" -o "$1" = "--get-nemo-logs0" ]; then #arg # get nemo_fishtank-nginx_1 logs shift 1 - echo "# inside debian-docker-in-docker container: docker logs nemo_fishtank-nginx_1 :" 1>&2 + echo "# inside debian-docker-in-docker container: docker logs nemo_fishtank-nginx$docker_log_postfix :" 1>&2 #(set -x; docker exec -ti "$docker_outer__container_name" docker logs nemo_fishtank-nginx_1) - (set -x; docker exec "$docker_outer__container_name" docker logs nemo_fishtank-nginx_1) + (set -x; docker exec "$docker_outer__container_name" docker logs "nemo_fishtank-nginx$docker_log_postfix") echo 1>&2 elif [ "$1" = "--logs1" -o "$1" = "--get-nemo-logs1" ]; then #arg # get nemo_fishtank_1 logs shift 1 - echo "# inside debian-docker-in-docker container: docker logs nemo_fishtank_1 :" 1>&2 - #(set -x; docker exec -ti "$docker_outer__container_name" docker logs nemo_fishtank_1) - (set -x; docker exec "$docker_outer__container_name" docker logs nemo_fishtank_1) + echo "# inside debian-docker-in-docker container: docker logs nemo_fishtank$docker_log_postfix :" 1>&2 + #(set -x; docker exec -ti "$docker_outer__container_name" docker logs "nemo_fishtank$docker_log_postfix") + (set -x; docker exec "$docker_outer__container_name" docker logs "nemo_fishtank$docker_log_postfix") echo 1>&2 elif [ "$1" = "--logsall" -o "$1" = "--get-nemo-logsall" ]; then #arg # get all nemo_*logs @@ -425,10 +435,15 @@ elif [ "$1" = "--logsall" -o "$1" = "--get-nemo-logsall" ]; then #arg # get all (set -x; docker exec "$docker_outer__container_name" sh -c "docker ps | awk 'NR>1 { print \$0; }' | while read id rest; do echo \"#\$id \$rest\"; docker logs \"\$id\"; echo; done") echo 1>&2 +elif [ "$1" = "--logsall2" ]; then #arg # determine all active log files in nemo container + shift 1 + + (set -x; docker exec "$docker_outer__container_name" sh -c "lsof -Pn -w | awk '\$(NF) ~ /\\.log$/ && /\\s[0-9]+w\\s+REG\\s/ { print dirprefix \$(NF); }' dirprefix=\"\$1\" | sort -u" -- "/proc/$(docker inspect "$docker_outer__container_name" | awk '/"Pid":/ { sub(/,$/, ""); print $2; }')/root") + elif [ "$1" = "--logsall2.tailf" ]; then #arg # run tail -f on all active log files in nemo container shift 1 - (set -x; docker exec "$docker_outer__container_name" sh -c "tail -f \$(lsof -Pn -w | awk '\$(NF) ~ /\.log$/ && /w\\s+REG/ { print \$(NF); }' | sort -u)") + (set -x; docker exec "$docker_outer__container_name" sh -c "tail -f \$(lsof -Pn -w | awk '\$(NF) ~ /\\.log$/ && /\\s[0-9]+w\\s+REG\\s/ { print \$(NF); }' | sort -u)") # @@ -505,26 +520,74 @@ elif [ "$1" = "--freertr-host1-ping-host2" ]; then #arg # enter host1 container exec docker exec -ti host1 ping 10.2.10.12 +elif [ "$1" = "--freertr-host1-ping-host2.bg" ]; then #arg # enter host1 container and run ping host2 + shift 1 + + docker exec host1 sh -c "type screen >/dev/null 2>/dev/null || apt-get install -yyy screen" + docker exec host1 screen -S ping2 -d -m ping 10.2.10.12 + elif [ "$1" = "--freertr-host2-ping-host1" ]; then #arg # enter host2 container and run ping host1 shift 1 exec docker exec -ti host2 ping 10.1.10.11 +elif [ "$1" = "--freertr-host2-ping-host1.bg" ]; then #arg # enter host2 container and run ping host1 + shift 1 + + docker exec host2 sh -c "type screen >/dev/null 2>/dev/null || apt-get install -yyy screen" + docker exec host2 screen -S ping1 -d -m ping 10.1.10.11 + elif [ "$1" = "--freertr-tshark-netconf" ]; then #arg # enter freertr container and run tshark on eth3, in order to monitor netconf traffic towards nemo container shift 1 - exec docker exec -ti freertr tshark -T text -V -f 'port 9995' -d udp.port==9995,cflow -i eth3 + exec docker exec -ti freertr tshark -T text -V -f 'port 9995' -d udp.port==9995,cflow -i eth3 "$@" elif [ "$1" = "--nemo-tshark-netconf" ]; then #arg # enter (outer) nemo d-in-d container and run tshark on eth1, in order to monitor netconf traffic from freertr container shift 1 - exec docker exec -ti "$docker_outer__container_name" tshark -T text -V -f 'port 9995' -d udp.port==9995,cflow -i eth1 + exec docker exec -ti "$docker_outer__container_name" tshark -T text -V -f 'port 9995' -d udp.port==9995,cflow -i eth1 "$@" -elif [ "$1" = "--nemo-get-filename-of-cerfile" ]; then #arg # show filename of client certificate filename (as seen from outside of outer nemo d-in-d container) +elif [ "$1" = "--nemo-get-filename-of-certfile" ]; then #arg # show filename of client certificate filename (as seen from outside of outer nemo d-in-d container) shift 1 echo "/proc/$(docker inspect "$docker_outer__container_name" | awk ' /"Pid":/ { sub(/,$/, ""); print $2; }')/root/nemo-all/secrets/CA/admin.p12" +elif [ "$1" = "--nemo-get-dirname-onhost" ]; then #arg # show dirname of inside container dir /nemo-all/ as seen from outside on the host + shift 1 + + echo "/proc/$(docker inspect "$docker_outer__container_name" | awk ' /"Pid":/ { sub(/,$/, ""); print $2; }')/root/nemo-all/" + +#arg + +elif [ "$1" = "--allx" ]; then #arg # all-in-one mode + shift 1 + + set -e + set -x + + "$0" --all1 + + "$0" --freertr-testnet-prep-and-run + "$0" --freertr-host2-ping-host1.bg + "$0" --freertr-host1-ping-host2.bg + + # test tshark + "$0" --nemo-tshark-netconf -a duration:20 + + "$0" --exec ./install_and_run_vsmd --install_only + + echo + echo "# logfiles in outer nemo container:" + "$0" --logsall2 + + echo + echo "# nemo installation dir in outer nemo container:" + "$0" --nemo-get-dirname-onhost + + echo + echo "# client cert file:" + "$0" --nemo-get-filename-of-certfile + #arg else diff --git a/inst/testing/nemo1/nemo.conf.vsmd b/inst/testing/nemo1/nemo.conf.vsmd new file mode 100644 index 0000000000000000000000000000000000000000..95ff3deab344570ae9e258f88d05100af79e0a3c --- /dev/null +++ b/inst/testing/nemo1/nemo.conf.vsmd @@ -0,0 +1,29 @@ +[vsmd] +countermeasurectl: /opt/countermeasure/countermeasure.py +offrampctl: /bin/echo +flowspec_redirect: 65023:172 + +#rpc_host: localhost +rpc_host: 172.18.0.1 +rpc_port: 3236 + +sqlite_db: /services/data/vsmd/vsmd.sqlite + +#ssl_key: /services/etc/nemo/ssl/testvm.test.org.key +#ssl_cert: /services/etc/nemo/ssl/testvm.test.org.pem +#ssl_ca: /services/etc/nemo/ssl/test-ca-chain.pem +ssl_key: /nemo-all/secrets/nemo-analyse.key +ssl_cert: /nemo-all/secrets/nemo-analyse.pem +ssl_ca: /nemo-all/secrets/nemo-analyse-cachain.pem + +stats_interval: 60 + +[nemo_identities] + +# TODO: replace by actual fingerprint? of cert: +F13A90C5F2637C6AECF744126D6BE46A27BDACCE: Nemo Testinstanz + +[Nemo Testinstanz] +cidr_ro: 10.0.1.0/24 +cidr_rw: 127.0.0.0/8 +