RouterOS Export Anonymizer Script


RouterOS Export Anonymizer Perl Script

Perl script

When posting to the Mikrotik forum it often is necessary to include the exported configuration to provide all necessary information and all details.

Unfortunately, the /export command reveals all information, no difference wether it’s sensitive information or not. This way people by accident post MAC and IP addresses, SSIDs and WLAN passwords to a public forum. I think all these data should better not be posted, even if it’s posted anonymously.

The perl script below removes all sensitive information and replaces them with labels, so it should still be possible to get the whole picture.

In case you find some configurations which the script does not filter correctly, feel free to post in the comments so I can fix the script.

Usage

$ cat export.rsc | routeros-export-anonymizer.pl > anonymous-export.rsc

Script

#!/usr/bin/perl -w

# #############################################################################
# Replace all sensitive information like MAC and IP addresses, SSIDs
# and specific names for interfaces, bridges etc. with general labels.
# #############################################################################

use strict;

my ($command_area) = '';
my ($id_ssid) = 1;
my ($id_wpakey) = 1;
my (%labels);
my (@filedata) = ();


# #############################################################################
# Parse the line passed as argument for fields labeled "name" and store them
# in %labels, where the general label is generated by the last part of the
# last seen RouterOS / command (e.g. /interface ethernet) and a unique number.
sub find_labels
  {
    my ($line) = @_;

    if ($line =~ m:^/:)
      {   # found a new command area
        $command_area = $line;
        $command_area =~ s/^.*\s//;
        $command_area =~ s/-/_/g;
        $command_area =~ tr/a-z/A-Z/;
      }
    elsif ($line =~ m/ name="([^"]*)"/ ||
        $line =~ m/ name=([^\s]*)\b/)
      {   # found a line containing a new label
        my ($name) = $1;
        my ($id) = 1;

        # find the next free id in this command area
        while (defined($labels{$command_area . '_' . $id}))
          { $id++; }

        # store the new label
        $labels{$command_area . '_' . $id} = $name;
      }
  }


# #############################################################################
# Replace all collected labels
# %labels contains labels as keys and specific/sensitive data as values
sub replace_labels
  {
    my ($max_line) = $#filedata;

    for (my $i = 0; $i <= $max_line; $i++)
      {
        foreach my $key (keys %labels)
          {
            $filedata[$i] =~ s/$labels{$key}/$key/;
          }
      }
  }


# #############################################################################
# Replace information in place, like MAC and IP addresses and SSIDs
sub replace_secrets
  {
    my ($line) = @_;

    # replace SSIDs
    if ($line =~ s/ ssid="[^"]*"/ ssid=SSID_$id_ssid/)
      { $id_ssid++; }
    elsif ($line =~ s/ ssid=[^\s]*(\b)/ ssid=SSID$2/)
      { $id_ssid++; }

    # replace WPA keys
    if ($line =~ s/ wpa-pre-shared-key="[^"]*"/ wpa-pre-shared-key=KEY_$id_wpakey/)
      { $id_wpakey++; }
    elsif ($line =~ s/ wpa-pre-shared-key=[^ ]*(\b)/ wpa-pre-shared-key=KEY_$id_wpakey$1/)
      { $id_wpakey++; }
    if ($line =~ s/ wpa2-pre-shared-key="[^"]*"/ wpa2-pre-shared-key=KEY_$id_wpakey/)
      { $id_wpakey++; }
    elsif ($line =~ s/ wpa2-pre-shared-key=[^ ]*(\b)/ wpa2-pre-shared-key=KEY_$id_wpakey$1/)
      { $id_wpakey++; }

    # replace MAC addresses
    while ($line =~ s/[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:([0-9A-F]{2}:[0-9A-F]{2})/XX:XX:XX:XX:$1/)
      { ; }
    # replace ip addresses
    while ($line =~ s/[0-9]{1,3}\.[0-9]{1,3}\.([0-9]{1,3}\.[0-9]{1,3})/xxx.xxx.$1/)
      { ; }

    return $line;
  }


# #############################################################################
# Main routine which iterates over STDIN and writes to STDOUT after processing
# the input.
# Commands across multiple lines (concatenated by \ at the end of line) are
# converted into single lines.
sub main
  {
    my ($last) = '';
    my ($line);

    while (defined($line = ))
      {
        if ($last ne '')
          {   # the last line was terminated by \
            # remove leading 4 spaces
            $line =~ s/^    //;
            # remove the terminating \ at eol
            $last =~ s/\\$//;
            # concat last and current line
            $line = $last . $line;
          }
        # remove CR/LF at eol
        $line =~ s/\r\n//g;

        if ($line =~ m/\\$/)
          {   # if the line terminates with \ there is nothing to do
            $last = $line;
          }
        else
          {   # process line
            $line = replace_secrets($line);
            find_labels($line);
            push(@filedata, $line);
            $last = '';
          }
      }

    replace_labels();

    while (@filedata)
      { print shift(@filedata) . "\n"; }
  }


# #############################################################################

main();

# #############################################################################

Leave a comment

Your email address will not be published. Required fields are marked *