#1
  1. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71

    Sockets within threads problem


    I have a forked process that is supposed to scan an IP subnet.
    Forked process
    . |->thread 1
    . | |->loop through ports X,Y,Z...
    . |->thread 2
    . | |->loop through ports X,Y,Z...
    . |->thread 3
    . | |->loop through ports X,Y,Z...
    . |->thread X
    . .....
    For every IP I create one thread and within the thread I iterate over some ports.
    I also make sure that I keep just a certain number of threads running to be nice to OS.
    The scenario works well up to the line of creating the INET socket. As soon as I do so the whole subprocess silently quits. Commenting out the socket object creation line makes the whole loop over the ports run to the end smoothly.

    Don't know what the problem may be.

    This code does not work as needed:
    Code:
    ...
            while($ipobj->intip() <= $ipobj->last_int()){
                    last if $ipobj->intip() == $ipobj->last_int();
                    my $i=$ipobj->ip;
                    ++$ipobj;
                    my $thr;
                    $thr=threads->create(\&_ScanLevel1,$i,$self->{ports});
                    push(@threads,\$thr);
                    &CleanupThreads(\@threads) if(scalar(@threads)==20);
            }
    
    sub _ScanLevel1{
            my $ipaddr=shift;
            my $ports=shift;
            foreach(split(/\|/,$ports)){
                    my $s=IO::Socket::INET->new(PeerAddr=>$ipaddr,PeerPort=>$_,Proto=>'tcp',Timeout=>1);
                    my $r=undef;
                    $r=1 if $s;
                    $s->close() if $s;
                    print "$ipaddr|$_|$r\n";
            }
            return 1;
    }
    ...
    This code works (doesn't terminates its parent process):
    Code:
    ...
            while($ipobj->intip() <= $ipobj->last_int()){
                    last if $ipobj->intip() == $ipobj->last_int();
                    my $i=$ipobj->ip;
                    ++$ipobj;
                    my  $s=IO::Socket::INET->new(PeerAddr=>$i,PeerPort=>22,Proto=>'tcp',Timeout=>1);
                    my $r=undef;
                    $r=1 if $s;
                    $s->close() if $s;
                    print "$i|$r\n";
                    next;
                    my $thr;
                    $thr=threads->create(\&_ScanLevel1,$i,$self->{ports}) if $self->{'level'}==1;
                    push(@threads,\$thr);
                    &CleanupThreads(\@threads) if(scalar(@threads)==20);
            }
    ....
    This code works as well (doesn't terminate its parent process):
    Code:
    ...
            while($ipobj->intip() <= $ipobj->last_int()){
                    last if $ipobj->intip() == $ipobj->last_int();
                    my $i=$ipobj->ip;
                    ++$ipobj;
                    my $thr;
                    $thr=threads->create(\&_ScanLevel1,$i,$self->{ports});
                    push(@threads,\$thr);
                    &CleanupThreads(\@threads) if(scalar(@threads)==20);
            }
    
    sub _ScanLevel1{
            my $ipaddr=shift;
            my $ports=shift;
            foreach(split(/\|/,$ports)){
                    print "$ipaddr|$_\n";
            }
            return 1;
    }
    
    ...
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    71
    Rep Power
    2
    Which ports are you looping through?
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71
    The basic group: 22,21,23,80,161 (that's what I test now)
    In reality a user will specify ports upon a new subnet scan process creation or its modification.
    So 443, 8080, 8443, 1521, 3306, 161 etc. .

    I have also found out that there could be a major problem with the Timeout option presence upon the IO::Socket::INET object creation.

    The goal is - obviously - to run the subprocesses independently (per subnet) and the threads "independetly" (per IP). Testing open ports is done sequencialy though.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,937
    Rep Power
    1225
    This is not an answer to your question but based on your code and description of what you're doing, nmap would be a better solution.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71
    Originally Posted by FishMonger
    This is not an answer to your question but based on your code and description of what you're doing, nmap would be a better solution.
    Thank you. Let me look.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,937
    Rep Power
    1225
    Originally Posted by zby
    Thank you. Let me look.
    If you decide to go with nmap, then you may also want to look at the related cpan modules that interface with nmap.

    Nmap::Scanner - Perform and manipulate nmap scans using perl
    Nmap::Parser - parse nmap scan data with perl
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71
    Yep. I've just glanced at it 'cause I have to go now.
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71
    This works fine printing Nmap::Scanner=HASH(0x....) for each IP (aka thread):
    Code:
    ...
    sub _ScanLevel1{
            my $ipaddr=shift;
            my $ports=shift;
            my $scanner=new Nmap::Scanner;
            $scanner->tcp_syn_scan();
            $scanner->max_rtt_timeout(1);
            $scanner->add_target($ipaddr);
            foreach(split(/\|/,$ports)){ $scanner->add_scan_port($_); }
            print $scanner."\n";
    }
    ...
    While this shoots down the whole forked process silently
    Code:
    ...
    sub _ScanLevel1{
            my $ipaddr=shift;
            my $ports=shift;
            my $scanner=new Nmap::Scanner;
            $scanner->tcp_syn_scan();
            $scanner->max_rtt_timeout(1);
            $scanner->add_target($ipaddr);
            foreach(split(/\|/,$ports)){ $scanner->add_scan_port($_); }
            my $r=$scanner->scan();
            print $r."\n";
    }
    ...
    It may have something to do with executing an OS command as the Nmap::Scanner does so in the background (/usr/bin/nmap).
    AND, the /usr/bin/nmap command has an SUID bit set as it requires it.
    Checking it out ...
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,937
    Rep Power
    1225
    Either remove or increase the max_rtt_timeout. Apparently, if set it needs to be at least 5.

    This is the actual nmap command that your sub executes (using my IP) and the output I received when ran from the command line.

    [root@099-91-RKB01 ~]# nmap -v -v -v -sS -p 22,21,23,80,161 --max_rtt_timeout 1 - 10.100.0.118
    Bogus --max-rtt-timeout argument specified, must be at least 5
    QUITTING!
    Last edited by FishMonger; October 25th, 2012 at 09:11 AM.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jul 2003
    Location
    Prague, Czech Republic
    Posts
    869
    Rep Power
    71
    No success.
    BUT, I have changed the thread stack_size from 4096 to 65536 and the execution point has moved on. Let me test first before trumpeting out ...

IMN logo majestic logo threadwatch logo seochat tools logo