Skip to content
Johnny Morano's Tech Articles

Johnny Morano's Tech Articles

Ramblings of an old-fashioned space cowboy

Menu
  • About
  • Privacy Policy
Menu

Syslog event generator with Net::RawIP (perl)

Posted on June 29, 2011July 28, 2011 by insaniac

Recently I have been asked to write a Syslog event generator, but not just a normal syslog generator, it had to be able to generate events coming from different hosts.

The normal ‘logger’ command sends Syslog messages using the machine’s IP address, so logger wasn’t very useful. The only thing useful seem to be, to generate my own Syslog packets in which I spoof the source address. After writing this handy little script, I realized that I’ve actually created a monster. A very evil scary kinda looking mean monster! I will show an example for creating Syslog event generator (and later on one for creating SNMP events), but the code can be used for much more. Please keep in mind I post this code just for educational and debugging reasons. If you want to use it for other reasons… well that’s up to you! 🙂

The example shown overhere is a bit more worked out and put in an object oriented structure. It could have also been a simple quick and dirty script.

The module we will use is called Net::RawIP and it will allow us to create our TCP or UDP packets. We just need to figure out how packets should be created in order for the Syslog daemon to accept them.

At first I’ve created a Packet.pm class. This is the main base class, which creates the constructor and defines the class interface.

package Packet;
# $Id: Packet.pm 828 2011-06-28 13:05:03Z insaniac $
use strict; use warnings;
use Net::RawIP;

sub new {
    my($class, $opts) = @_;

    my $self = bless {}, $class || ref $class;
    $self->{rawip} = Net::RawIP->new($opts);

    return $self;
}

sub pkt_payload {
}

sub pkt_size {
}

sub pkt_debug {
}

sub pkt_send {
    my($self, $delay, $amount) = @_;

    $self->pkt_debug();
    $self->{rawip}->send($delay, $amount);
}

1;

Secondly I’ll need an UDP base class, from which the Syslog module will inherit.

package Packet::UDP;
# $Id: UDP.pm 837 2011-06-28 15:05:10Z insaniac $
use strict; use warnings;
use base qw/Packet/;
use POSIX qw{strftime};

#
# src => IP:PORT
# dst => IP:PORT
#
sub new {
    my($class, $src, $dst) = @_;
    my($saddr, $sport) = split /:/, $src;
    my($daddr, $dport) = split /:/, $dst;

    my $self = $class->SUPER::new({
            ip => {
                saddr    => $saddr,
                daddr    => $daddr,
                frag_off => 0,
                tos      => 0,
                id       => $$ + strftime('%s', localtime()),
            },
            udp => {
                source => $sport,
                dest   => $dport,
            },
            });
}

sub pkt_size {
    my($self)= @_;

    my($src, $dst, $data) = $self->{rawip}->get( {
                udp => [qw/source dest data/]
            },
    );
    my $size = length($src) + length($dst) + length($data);

    # set 'check' to 0 to recalculate the UDP checksum
    $self->{rawip}->set( {
            udp => {
                len   => $size,
                check => 0,
            }
    });

    return $size;
}

sub pkt_payload {
}

sub pkt_debug {
    my($self) = @_;

    my(@udp_fields) = qw/source dest len data/;
    my(@ip_fields)  = qw/version ihl tos id frag_off ttl protocolsaddr daddr/;
    my(@udp_data)   = $self->{rawip}->get({ udp => @udp_fields });
    my(@ip_data)    = $self->{rawip}->get({ ip  => @ip_fields });

    print "IP FIELDSn";
    print "=========n";
    print "- $ip_fields[$_]: $ip_data[$_]n" foreach 0 ..  $#ip_data;
    print "UDP FIELDSn";
    print "=========n";
    print "- $udp_fields[$_]: $udp_data[$_]n" foreach 0 ..  $#udp_data;

}

1;

Having all the base classes in place, we can finally focus on creating our Syslog class, a module which will allow us to send Syslog messages, allowing us to change the source IP address.

package Packet::UDP::Syslog;
# $Id: Syslog.pm 838 2011-06-28 15:08:07Z insaniac $
use strict; use warnings;
use base qw/Packet::UDP/;

sub new {
    my ($class, $src, $dst) = @_;
    my $self = $class->SUPER::new("$src:1666", "$dst:514");
    return $self;
}

# TAG               CODE    DESCRIPTION
# =====================================
# kernel            0       kernel messages
# user              1       user-level messages
# mail              2       mail system
# system            3       system daemons
# security          4       security/authorization messages (note 1)
# internal          5       messages generated internally by syslogd
# print             6       line printer subsystem
# news              7       network news subsystem
# uucp              8       UUCP subsystem
# clock             9       clock daemon (note 2)
# security2        10       security/authorization messages (note 1)
# ftp              11       FTP daemon
# ntp              12       NTP subsystem
# logaudit         13       log audit (note 1)
# logalert         14       log alert (note 1)
# clock2           15       clock daemon (note 2)
# local0           16       local use 0  (local0)
# local1           17       local use 1  (local1)
# local2           18       local use 2  (local2)
# local3           19       local use 3  (local3)
# local4           20       local use 4  (local4)
# local5           21       local use 5  (local5)
# local6           22       local use 6  (local6)
# local7           23       local use 7  (local7)
my $i = 0;
my %fac_map = map {$_ => $i++ } qw/kernel user mail system security internal print news uucp clock security2 ftp ntp logaudit logalert clock2 local0 local1 local2 local3 local4 local5 local6 local7/;

# TAG             CODE    DESCRIPTION
# =====================================
# emerg           0       Emergency: system is unusable
# alert           1       Alert: action must be taken immediately
# crit            2       Critical: critical conditions
# err             3       Error: error conditions
# warn            4       Warning: warning conditions
# notice          5       Notice: normal but significant condition
# info            6       Informational: informational messages
# debug           7       Debug: debug-level messages
$i = 0;
my %sev_map = map {$_ => $i++} qw/emerg alert crit err warn notice info debug/;

sub pkt_payload {
    my($self, $facility, $severity, $msg) = @_;

    my ($fac_sev) = ($fac_map{$facility} << 3) + $sev_map{$severity};
    $self->{rawip}->set({
            udp => { 
                data => "<$fac_sev>$msg�" 
                } 
            }
    );

    # call and set the size
    $self->pkt_size();
}

1;

Our OO structure is now ready, all we need is a script which will call all this code.

#!/usr/bin/perl
use strict; use warnings;
use lib './';
use Packet::UDP::Syslog;
use POSIX qw/strftime/;

my @sources = qw{
    166.59.83.200 166.59.83.1 166.59.83.206 192.168.0.99
    192.168.1.99
};

my @messages = (
        {severity => 'info',  payload => 'the planet is going down'},
        {severity => 'err',   payload => 'BOOM BOOM BOOM'},
        {severity => 'emerg', payload => 'The house is on fire!'},
        {severity => 'alert', payload => "Do NOT forget to feed the monkeysnAnd the bearsnand the cows!"},
        {severity => 'debug', payload => 'We should have a look into this'},
);

foreach my $src (@sources){
    my $syslog = Packet::UDP::Syslog->new($src, "192.168.1.3");
    foreach my $msg (@messages) {
        my $datetime = strftime("%b %d %H:%M:%S", localtime());
        $syslog->pkt_payload('local7', $msg->{severity}, $datetime." $src: ".$msg->{payload});
        $syslog->pkt_send(1,1);
    }
}

Running the script:

root@yamamoto:/home/insaniac/dev/Net# perl raw_pkt.pl
IP FIELDS
=========
- version: 4
- ihl: 5
- tos: 0
- id: 1309286460 
- frag_off: 0
- ttl: 64
- protocolsaddr: 3232235779
UDP FIELDS
=========
- source: 1666   
- dest: 514
- len: 68
- data: <190>Jun 28 17:12:13 166.59.83.200: the planet is going down
IP FIELDS
=========
- version: 4
- ihl: 5
- tos: 0
- id: 1309286460 
- frag_off: 0
- ttl: 64
- protocolsaddr: 3232235779
UDP FIELDS
=========
- source: 1666   
- dest: 514
- len: 58
- data: <187>Jun 28 17:12:14 166.59.83.200: BOOM BOOM BOOM
*** snip output ***

And that’s it! If we would check our receiving network interface (on IP address 192.168.1.3) with tcpdump, we would see our packets arriving:

17:13:24.218196 IP (tos 0x0, ttl 64, id 8359, offset 0, flags [none], proto UDP (17), length 96)
    166.59.83.206.1666 > musashi_vpn.syslog: [udp sum ok] SYSLOG, length: 68
        Facility local7 (23), Severity debug (7)
        Msg: Jun 28 17:13:24 166.59.83.206: We should have a look into this�x00
        0x0000:  3c31 3931 3e4a 756e 2032 3820 3137 3a31
        0x0010:  333a 3234 2031 3636 2e35 392e 3833 2e32
        0x0020:  3036 3a20 5765 2073 686f 756c 6420 6861
        0x0030:  7665 2061 206c 6f6f 6b20 696e 746f 2074
        0x0040:  6869 7300
        0x0000:  4500 0060 20a7 0000 4011 9e31 a63b 53ce
        0x0010:  c0a8 0103 0682 0202 004b cc9e 3c31 3931
        0x0020:  3e4a 756e 2032 3820 3137 3a31 333a 3234
        0x0030:  2031 3636 2e35 392e 3833 2e32 3036 3a20
        0x0040:  5765 2073 686f 756c 6420 6861 7665 2061
        0x0050:  206c 6f6f 6b20 696e 746f 2074 6869 7300
17:13:25.219101 IP (tos 0x0, ttl 64, id 8364, offset 0, flags [none], proto UDP (17), length 88)
    192.168.0.99.1666 > musashi_vpn.syslog: [udp sum ok] SYSLOG, length: 60
        Facility local7 (23), Severity info (6)
        Msg: Jun 28 17:13:25 192.168.0.99: the planet is going down�x00
        0x0000:  3c31 3930 3e4a 756e 2032 3820 3137 3a31
        0x0010:  333a 3235 2031 3932 2e31 3638 2e30 2e39
        0x0020:  393a 2074 6865 2070 6c61 6e65 7420 6973
        0x0030:  2067 6f69 6e67 2064 6f77 6e00
        0x0000:  4500 0058 20ac 0000 4011 d732 c0a8 0063
        0x0010:  c0a8 0103 0682 0202 0043 70bf 3c31 3930
        0x0020:  3e4a 756e 2032 3820 3137 3a31 333a 3235
        0x0030:  2031 3932 2e31 3638 2e30 2e39 393a 2074
        0x0040:  6865 2070 6c61 6e65 7420 6973 2067 6f69
        0x0050:  6e67 2064 6f77 6e00

10 thoughts on “Syslog event generator with Net::RawIP (perl)”

  1. Pierre says:
    February 8, 2012 at 08:53

    Hi Johnny

    wow, this is really cool. I know very little about perl and scripting, but I am faced with a problem whereby I am recieving a sh#tload of syslog messages from Cisco devices. They are all received by a CiscoWorks LMS server , they are then filtered and then forwarded to an another syslog collecting server. Thing is, that this collecting server “sees” all these messages coming from one device – which is the LMS server. I hope to use your script and modify this forwarding script so that it will show the original devices’ IP address.
    Cheers
    P

    Reply
    1. blank Johnny Morano says:
      February 16, 2012 at 08:48

      If you need help, I’m happy to assist 😉

      Reply
  2. blank blaxthos says:
    July 9, 2012 at 15:38

    This is great stuff, however… when I attempt to run the script as presented above, I receive the following error:

    dev@ubuntu:~/Documents/syslog_generator$ ./syslog_gen.pl
    Odd number of elements in anonymous hash at UDP.pm line 59.
    Can't use string ("source") as an ARRAY ref while "strict refs" in use at /usr/local/lib/perl/5.14.2/Net/RawIP.pm line 564.

    I’ve tried turning off strict, but still couldn’t get it working.

    Line 59 in UDP.pm:

    my(@udp_data) = $self->{rawip}->get({ udp => @udp_fields });

    Line 564 in RawIP.pm:

    map { ${$$hash{"$self->{proto}h"}}{$_} = '$' } @{$hash->{$self->{proto}}};

    Perl 5.14.2.

    Any ideas?

    Thanks!

    /b

    PS – running all with elevated permissions, just in case you need root to access Raw IP.

    Reply
    1. blank Johnny Morano says:
      July 12, 2012 at 12:25

      Hi,

      How does your ‘syslog_gen.pl’ script look like?

      Reply
      1. blank Michael Fread says:
        September 25, 2012 at 20:28

        I got these errors as well. The problem is that all the \ characters are missing in the UDP.pm code listing.

        Reply
  3. blank Chris says:
    March 9, 2013 at 20:23

    Yep \@udp_fields and \@ip_fields should be in UDP.pm

    However, what on earth is � in Syslog.pm? Without it, it doesnt send. With it you get \xEF\xBF on the end of the message?

    –Chris

    Reply
  4. blank Chris says:
    March 9, 2013 at 20:28

    Actually, it does work it just seems to be acting as padding, a space does the same job without the strange hex codes.

    Reply
  5. blank Sunil says:
    March 18, 2013 at 09:51

    Hi Johnny,

    I want to change my source IP from where syslog packet is being send e.g. ip address of my machine is 192.168.0.10 which is getting identified as ‘log source’ ip, instead of that I want 10.10.0.12 as a source IP, how to do that, please help.

    Thanks
    Sunil

    Reply
  6. blank Ben says:
    January 7, 2014 at 22:38

    I’m not quite clear of the filenames and directory structure that the 2nd & 3rd pieces of code should be saved in. Can you elaborate on that, or give more specifics?

    Reply
    1. blank Chris says:
      December 10, 2014 at 08:45

      Packet.pm goes under Packet, and in there have a directory UDP in which udp.pm goes, and in there a directory called syslog in which you put Syslog.pm. Easiest thing to do is have /Packet in the same directory as your perl script unless you end up better packaging your code

      Reply

Leave a Reply Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Posts

  • Use multiple Azure subscriptions in Terraform modules
  • Read the HAProxy UNIX socket file using Perl
  • A Prometheus Exporter framework written in Perl
  • Managing LDAP passwords with Perl
  • Libvirt guest startup issue with AppArmor
  • Deploy a PostgreSQL database with an initial schema using Ansible
  • Using Ansible to finalize Hashicorp Packer images

Categories

  • Automation (8)
  • Blog (60)
  • Database (4)
  • Development (37)
  • Linux (26)
  • Mac OS X (5)
  • Media (2)
  • OpenBSD (3)
  • Perl (34)
  • Photo (2)
  • PostgreSQL (4)
  • Terraform (5)
  • Web (11)

Tags

Ajax (3) Android (1) Ansible (2) API (5) AppArmor (1) Automation (5) Azure (3) azurerm (2) Bash (4) Cloud (2) CPAN (4) CSS (1) Debian (4) Dev (35) DevOps (11) EXIF (1) Facebook (1) Geotag (1) GMail (1) Google (3) Hack (2) Hashicorp (4) Hetzner (2) HTML (4) IMAP (2) IPTables (6) JavaScript (4) Libvirt (2) Linux (25) Logging (2) MacOSX (5) Media (2) Monitoring (6) MySQL (3) OpenBSD (4) Packer (1) Perl (35) PF (2) Postgresql (6) Security (7) SysAdmin (24) Terraform (4) Ubuntu (2) UNIX (9) Web 2.0 (3)

Archive

  • April 2022 (10)
  • March 2022 (6)
  • December 2016 (1)
  • March 2016 (1)
  • November 2015 (1)
  • November 2014 (1)
  • August 2014 (1)
  • May 2014 (1)
  • February 2014 (2)
  • December 2013 (1)
  • October 2013 (2)
  • September 2013 (2)
  • August 2013 (2)
  • October 2012 (1)
  • August 2012 (4)
  • March 2012 (3)
  • July 2011 (1)
  • June 2011 (2)
  • April 2011 (3)
  • March 2011 (4)
  • February 2011 (2)
  • December 2010 (2)
  • October 2010 (4)
  • September 2010 (1)
  • August 2010 (5)

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Footer

  • Shihai Corp
  • My Photo website
© 2022 Johnny Morano's Tech Articles | Powered by Superbs Personal Blog theme
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Do not sell my personal information.
Cookie SettingsAccept
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT