Page 1 of 3 123 LastLast
Results 1 to 10 of 29

Thread: Is there any way to grep a port range in netstat

  1. #1
    Join Date
    Sep 2009
    Location
    California U.S.A.
    Beans
    398

    Is there any way to grep a port range in netstat

    Right now I have
    Code:
    netstat --tcp --numeric |  cut -c 45-65 | sort -u | sed '/Foreign/d' | sed '/^$/d' | grep -e ':80' -e ':443'
    Which will show me all of my http stuff. I would like to continue to do this for Other protocols (email, ftp, etc..) The problem I have is that I cannot figure out how to grep something like :48620-:49150 I am not even sure that this is possible. If it is not then is there any way to create a list of those numbers in this format

    -e ':48620'
    -e ':48621'
    etc...

    So that I can just dump that into my script? Also, will that seriously affect the performance of the script if I have to do it that way because of the length? I read somewhere that this sort of thing can be done with sed but I am not really sure. Thanks in advance.

  2. #2
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Is there any way to grep a port range in netstat

    can't you extract the port part and check if it's greater than $lower_boundary and lower than $upper_boundary?

  3. #3
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Is there any way to grep a port range in netstat

    what i meant was: write a multiline script so you can play with data freely, use variables and stuff

    Code:
    #!/bin/bash
    
    lower=75
    upper=90
    
    #fifth column, skip first 2 rows (header)
    sockets=$(netstat --tcp --numeric | awk 'NR>2 {print $5}' )
    
    echo port range: $lower-$upper
    
    for socket in $sockets
    do
      ip=${socket%:*}
      port=${socket#*:}
      if (( $lower <= $port && $port <= $upper )) 
      then
        echo $socket \(port within range\)
      else
        echo $socket
      fi
    done
    Last edited by Vaphell; January 15th, 2011 at 08:37 AM.

  4. #4
    Join Date
    Sep 2009
    Location
    California U.S.A.
    Beans
    398

    Re: Is there any way to grep a port range in netstat

    Quote Originally Posted by Vaphell View Post
    what i meant was: write a multiline script so you can play with data freely, use variables and stuff

    Code:
    #!/bin/bash
    
    lower=75
    upper=90
    
    #fifth column, skip first 2 rows (header)
    sockets=$(netstat --tcp --numeric | awk 'NR>2 {print $5}' )
    
    echo port range: $lower-$upper
    
    for socket in $sockets
    do
      ip=${socket%:*}
      port=${socket#*:}
      if (( $lower <= $port && $port <= $upper )) 
      then
        echo $socket \(port within range\)
      else
        echo $socket
      fi
    done
    So the lower and upper are variables that you set yourself? Can "lower" and "upper" be anything as long as they are followed with =number? Also, how could I pull out the extra data that I do not need? What does

    Code:
    for socket in $sockets
    mean? I am curious too about this

    Code:
    ip=${socket%:*}
    port=${socket#*:}
    Thanks by the way.

  5. #5
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Is there any way to grep a port range in netstat

    So the lower and upper are variables that you set yourself? Can "lower" and "upper" be anything as long as they are followed with =number?
    yes, they are hardcoded at the beginning in my example
    you create variables
    Code:
    variable=<value>
    and use them with $ sign, eg
    Code:
    echo $variable
    some_program $variable
    you can also assign script parameters there, if you run your script with
    Code:
    my_script <lower> <upper>
    then you can assign parameter values to 'lower' and 'upper' variables
    Code:
    lower=$1
    upper=$2
    $1 = first param, $2 = 2nd param

    Also, how could I pull out the extra data that I do not need?
    what would you want exactly here? filter out 80 and 443? you can modify the command to suit your needs (pipe it to grep like you did) or simply do nothing inside the 'for' loop when port = 80 or 443 (if statement)


    for socket in $sockets
    as you can see in the script 'sockets' variable stores the output of the command in $()
    later 'for' loop puts its hands on that variable, takes each 'word' (delimited by whitespace) which happens to be in the IP:port format and assigns it to socket variable. Between 'do' and 'done' you get to play with the current value of $socket. In other words it iterates the set of sockets and $socket stores current socket so you can access it.

    ip=${socket%:*}
    port=${socket#*:}
    this extracts a substring from the socket (ip:port)
    ip=${socket%:*} means get the part of $socket that is BEFORE ':*', meaning ': followed by any sequence of chars' and store it in $ip
    port=${socket#*:} means get the part of $socket that is AFTER '*:', meaning 'any sequence of chars followed by :' and store it in $port

    if you want to write scripts, find some bash manual on the net and dive in - you won't regret it
    Last edited by Vaphell; January 15th, 2011 at 11:02 AM.

  6. #6
    Join Date
    Sep 2009
    Location
    California U.S.A.
    Beans
    398

    Re: Is there any way to grep a port range in netstat

    what would you want exactly here? filter out 80 and 443? you can modify the command to suit your needs (pipe it to grep like you did) or simply do nothing inside the 'for' loop when port = 80 or 443 (if statement)
    I guess what I am really trying to do after reading through this is to define a number range as one variable or grep two variables at once. What I did was

    Code:
    grep -e ':80' -e ':443'
    which was simple enough. But the problem I ran into is that if I wish to use a range like
    49152 through 65535
    (private ports usually used on my machine for bittorrent traffic)

    I cannot really grep -e that. Well I could but I figure that there has got to be another way. I guess another way I could do this is to set a variable of anything above 49152. But then later when I am plugging in unassigned port ranges I
    would have to know how to do this anyways.

    if you want to write scripts, find
    some bash manual on the net and dive in -
    you won't regret it
    I have looked at a few manuals and right now I am watching a video series on unix shell scripting. But to be honest I have learned and accomplished more on these forums than I have ever been able to with self study. It is like when I read some of these books and the author explains something I still don't get it. I am starting to understand man pages. But, I still feel that they could be a little less cryptic. Also, people here give me real examples that I can actually use and that mean something to me which has significantly helped me in learning newthings. Do you have any books or videos that you would highly recommend?

  7. #7
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Is there any way to grep a port range in netstat

    to be honest i learnt most of stuff by having a goal and googling for complete/partial answers - you know: 'linux cut substring', 'linux replace string' or something like that you will get like dozens of possibilities using different tools. At first you use 3 tools for everything but with time you get to know more and more tools and ways of doing stuff.

    back to the port ranges:
    - i noticed it just now - your ":80" and ":443" will fail for ":8011" or ":4433", you need to test if next char is whitespace \s or end-of-line $ (depending on situation)

    fancy regex in grep to cover port ranges could work but it would be an absolute pain in the a$s to write and giving grep thousands of expressions (to cover each port of the range in naive way) to search is not cool.
    Problem with patterns is that they don't get into logic behind the characters. For most tools integers is just a bunch of 0-9 characters not a number and is up to the user to add actual logic.
    Maybe there is some magic one-liner or a combination of netstat parameters that can do your stuff but when you don't know it, there is nothing wrong with writing more verbose script without obscure hacks.

    upgraded script
    Code:
    #!/bin/bash
    
    if [ "$#" == "0" ]
    then
      #default values
      ports=(  80     443       8000-9000   3000-5000 )
      labels=( "HTTP" "HTTPS"   "SOMETHING"   "TORRENT" )
    else
      #script arguments
      i=0
      while (( "$#" ))
      do
        ports[i]=$1
        shift
        labels[i]=$1
        shift
        i=$((i+1))
      done
    fi
    
    sockets=$( netstat --tcp --numeric | awk 'NR>2 {print $5}' )
    size=${#ports[@]}
    
    #calculate arrays of $lower and $upper from $ports array
    for (( i=0; i<${size}; i++ ))
    do
      lower[i]=${ports[i]%-*}
      upper[i]=${ports[i]#*-}
    done
    
    for socket in $sockets
    do
      ip=${socket%:*}
      port=${socket#*:}
      #iterate arrays of $lower and $upper to see if $port matches
      for (( i=0; i<${size}; i++ ))
      do
        if (( ${lower[i]} <= $port && $port <= ${upper[i]} )) 
        then
          echo $socket ${labels[i]}
          break
        fi
      done
    done
    Ports is an array of port ranges - single number means single port, x-y means from x to y, labels is an array of related labels assigned to ports (labels[i] describes ports[i]). You can modify these 2 at will - the only condition is that numbers of elements match, so use "" if you don't want a label. $size keeps the size of arrays so i can use it later to iterate easily over them.
    from $ports array $lower and $upper arrays are calculated (stuff before - and stuff after - in $ports element, single port has no '-' so the whole string is returned, thus $lower=$upper)

    next step is actual analysis. As you can see, netstat command is not grepped so the script tests each line of the netstat output. Each socket is tested against the range of $lower and $upper and if the port matches, $socket is printed out with the associated label.
    As a bonus, thanks to labels you can run this script and easily pipe it to grep to display only a subset of sockets.
    Also it's possible to rework this script to accept parameters, eg
    Code:
    my_script <port1> <label1> <port2> <label2> ...
    and populate the arrays from parameters so it's even more flexible.

    EDIT: added support for script arguments - not entirely foolproof, assumes even number of params, use "" for no label
    Last edited by Vaphell; January 16th, 2011 at 09:51 PM.

  8. #8
    Join Date
    Sep 2009
    Location
    California U.S.A.
    Beans
    398

    Re: Is there any way to grep a port range in netstat

    [QUOTE=Vaphell;10365255]
    to be honest i learnt most of stuff by having a goal and googling for complete/partial answers
    I could not agree more. This is the only real method I have ever known before joining these forums.
    - i noticed it just now - your ":80" and ":443" will fail for ":8011" or ":4433", you need to test if next char is whitespace \s or end-of-line $ (depending on situation)
    Thank you for the tip. So, instead of
    Code:
    grep -e ":80"
    I would have to use
    Code:
    grep -e ":80 "
    I am going to change my script right now accordingly.

    fancy regex in grep to cover port ranges could work but it would be an absolute pain in the a$s to write and giving grep thousands of expressions (to cover each port of the range in naive way) to search is not cool.
    This is my problem. Right on the money.


    upgraded script
    Code:
    #!/bin/bash
    
    if [ "$#" == "0" ]
    then
      #default values
      ports=(  80     443       8000-9000   3000-5000 )
      labels=( "HTTP" "HTTPS"   "SOMETHING"   "TORRENT" )
    else
      #script arguments
      i=0
      while (( "$#" ))
      do
        ports[i]=$1
        shift
        labels[i]=$1
        shift
        i=$((i+1))
      done
    fi
    sockets=$( netstat --tcp --numeric | awk 'NR>2 {print $5}' )
    
    size=${#ports[@]}
    echo ${ports[@]}
    echo ${labels[@]}
    
    
    #calculate arrays of $lower and $upper from $ports array
    for (( i=0; i<${size}; i++ ))
    do
      lower[i]=${ports[i]%-*}
      upper[i]=${ports[i]#*-}
    done
    
    for socket in $sockets
    do
      ip=${socket%:*}
      port=${socket#*:}
      #iterate arrays of $lower and $upper to see if $port matches
      for (( i=0; i<${size}; i++ ))
      do
        if (( ${lower[i]} <= $port && $port <= ${upper[i]} )) 
        then
          echo $socket ${labels[i]}
          break
        fi
      done
    done
    Ports is an array of port ranges - single number means single port, x-y means from x to y, labels is an array of related labels assigned to ports (labels[i] describes ports[i]). You can modify these 2 at will - the only condition is that numbers of elements match, so use "" if you don't want a label. $size keeps the size of arrays so i can use it later to iterate easily over them.
    from $ports array $lower and $upper arrays are calculated (stuff before - and stuff after - in $ports element, single port has no '-' so the whole string is returned, thus $lower=$upper)

    next step is actual analysis. As you can see, netstat command is not grepped so the script tests each line of the netstat output. Each socket is tested against the range of $lower and $upper and if the port matches, $socket is printed out with the associated label.
    As a bonus, thanks to labels you can run this script and easily pipe it to grep to display only a subset of sockets.
    Also it's possible to rework this script to accept parameters, eg
    Code:
    my_script <port1> <label1> <port2> <label2> ...
    and populate the arrays from parameters so it's even more flexible.

    EDIT: added support for script arguments - not entirely foolproof, assumes even number of params, use "" for no label
    I am having a real hard time wrapping my head around this. I need to sit down and study this for a while. One thing I did notice is that you ended the script with "done" instead of "exit" Does that do the same thing? Is there an advantage to using one over the other?

  9. #9
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: Is there any way to grep a port range in netstat

    i can explain some minute details if you wish, no problem - just ask

    One thing I did notice is that you ended the script with "done" instead of "exit"
    there is no ending at all, script will end either way so why bother. done ends 'for' loops
    in the last part there are 2 loops, one embedded in another - so there are 2 done's at the end

    Code:
    for ... #outer loop
      for ... #inner loop
    
      done #inner loop
    done #outer loop

  10. #10
    Join Date
    Sep 2009
    Location
    California U.S.A.
    Beans
    398

    Re: Is there any way to grep a port range in netstat

    i can explain some minute details if you wish, no problem - just ask
    I still need to figure out how a loop works. Give me a little while to do some googling and some tests so that I can understand a little better what is going on here.


    there is no ending at all, script will end either way so why bother. done ends 'for' loops
    in the last part there are 2 loops, one embedded in another - so there are 2 done's at the end
    So is putting exit at the end of a script just a waste of time? I do have an additional question for you (a little off topic). I created a script that starts some applications when my computer starts.

    Code:
    #! /bin/bash
    
    sleep 10 && evolution & firefox-4.0 & sleep 20 && devilspie -a &  sleep 25 && pkill -f "devilspie -a"
    
    
    
    exit
    But when I looked into my system monitor I noticed that "startupopen.sh" (the name of the script above) is still running after it executes. So, I created another script
    Code:
    #! /bin/bash
    
    
    sleep 55 && pkill startupopen.sh
    
    
    exit
    which kills the first one. Is there a better way to do this from the original script instead of needing to call on an additional one? This does not seem possible because how could a running script kill itself? Just curious if you ever came across this. Also, I noticed in your script and some others I have seen that the code is indented on certain lines. Is that something that you do yourself or are you using a certain editor that does that for you? Anyways, give me a little time to study and when I understand a little more I will get back to you.

Page 1 of 3 123 LastLast

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •