One place for hosting & domains

      Learning

      Learning Go Functions, Loops, and Errors – A Tutorial


      Updated by Linode Contributed by Mihalis Tsoukalos

      Introduction

      Go is a modern, open source, and general-purpose programming language that began as an internal Google project and was officially announced at the end of 2009. Go was inspired by many other programming languages including C, Pascal, Alef, and Oberon. Its spiritual fathers were Robert Griesemer, Ken Thomson, and Rob Pike, who all designed Go as a language for professional programmers that want to build reliable, robust, and efficient software. Apart from its syntax and its standard functions, Go comes with a rich standard library.

      In this Guide

      This guide will cover the following topics:

      Note

      This guide was written with Go version 1.13.

      Before You Begin

      1. You will need Go installed on your computer. To get it, go to Go’s official download page and get the installer for your operating system, or you can install it from source. Follow the installation instructions for your operating system.

      2. Add /usr/local/go/bin to the PATH environment variable:

        export PATH=$PATH:/usr/local/go/bin
        

        You may need to restart your shell for this change to apply.

      The Advantages of Go

      Although Go is not perfect, it has many advantages, including the following:

      • It is a modern programming language that was made by experienced developers for developers.
      • The code is easy to read.
      • Go keeps concepts orthogonal, or simple, because a few orthogonal features work better than many overlapping ones.
      • The compiler prints practical warnings and error messages that help you solve the actual problem.
      • It has support for procedural, concurrent, and distributed programming.
      • Go supports garbage collection so you do not have to deal with memory allocation and deallocation.
      • Go can be used to build web applications and it provides a simple web server for testing purposes.
      • The standard Go library offers many packages that simplify the work of the developer.
      • It uses static linking by default, which means that the produced binary files can be easily transferred to other machines with the same OS and architecture. As a consequence, once a Go program is compiled successfully and the executable file is generated, the developer does not need to worry about dependencies and library versions.
      • The code is portable, especially among UNIX machines.
      • Go can be used for writing UNIX systems software.
      • It supports Unicode by default which means that you do not need any extra code for printing characters from multiple human languages or symbols.

      Executing Go code

      There are two kinds of Go programs: autonomous programs that are executable, and Go libraries. Go does not care about an autonomous program’s file name. What matters is that the package name is main and that there is a single main() function in it. This is because the main() function is where program execution begins. As a result, you cannot have multiple main() functions in the files of a single project.

      A Simple Go program

      This is the Go version of the Hello World program:

      ./helloworld.go
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      package main
      
      import (
          "fmt"
      )
      
      func main() {
          fmt.Println("Hello World!")
      }
      • All Go code is delivered within Go packages. For executable programs, the package name should be main. Package declarations begin with the package keyword.

      • Executable programs should have a function named main() without any function parameters. Function definitions begin with the func keyword.

      • Go packages might include import statements for importing Go packages. However, Go demands that you use some functionality from each one of the packages that you import. There is a way to bypass this rule, however, it is considered a bad practice to do this.

        The helloworld.go file above imports the fmt package and uses the fmt.Println() function from that package.

        Note

        All exported package functions begin with an uppercase letter. This follows the Go rule: if you export something outside the current package, it should begin with an uppercase letter. This rule applies even if the field of the Go structure or the global variable is included in a Go package.

      • Go statements do not need to end with a semicolon. However, you are free to use semicolons if you wish. For more information on formatting with curly braces, see the section below.

      1. Now that you better understand the helloworld.go program, execute it with the go run command:

        go run helloworld.go
        

        You will see the following output:

          
        Hello World!
        
        

        This is the simplest of two ways that you can execute Go code. The go run command compiles the code and creates a temporary executable file that is automatically executed and then it deletes that temporary executable file. This is similar to using a scripting programming language.

      2. The second method to execute Go code is to use the build command. Run the following command to use this method:

        go build helloworld.go
        

        The result of that command is a binary executable file that you have to manually execute. This method is similar to the way you execute C code on a UNIX machine. The executable file is named after the Go source filename, which means that in this case the result will be an executable file named helloworld. Go creates statically linked executable files that have no dependencies to external libraries.

      3. Execute the helloworld file:

        ./helloworld
        

        You will see the following output:

          
        Hello World!
        
        

        Note

        The go run command is usually used while experimenting and developing new Go projects. However, if you need to transfer an executable file to another system with the same architecture, you should use go build.

      Formatting Curly Braces

      The following version of the “Hello World” program will not compile:

      ./curly.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      
      package main
      
      import (
          "fmt"
      )
      
      func main()
      {
          fmt.Println("Hello World!")
      }
      1. Execute the program above, and observer the error message generated by the compiler:

        go run curly.go
        
          
        # command-line-arguments
        ./curly.go:7:6: missing function body
        ./curly.go:8:1: syntax error: unexpected semicolon or newline before {
        
        
      • This error message is generated because Go requires the use of semicolons as statement terminators in many contexts and the compiler automatically inserts the required semicolons when it thinks that they are necessary. Putting the opening curly brace ({) on its own line makes the Go compiler look for a semicolon at the end of the previous line (func main()), which is the cause of the error message.

      • There is only one way to format curly braces in Go; the opening curly brace must not appear on it’s own line. Additionally, you must use curly braces even if a code block contains a single Go statement, like in the body of a for loop. You can see an example of this in the first version of the helloworld.go program or in the Loops in Go section.

      The Assignment Operator and Short Variable Declarations

      • Go supports assignment (=) operators and short variable declarations (:=).
      • With := you can declare a variable and assign a value to it at the same time. The type of the variable is inferred from the given value.
      • You can use = in two cases. First, to assign a new value to an existing variable and second, to declare a new variable, provided that you also give its type.

        For example, var aVariable int = 10, is equivalent to aVariable := 10 assuming aVariable is an int.

      • When you specifically want to control a variable’s type, it is safer to declare the variable and its type using var and then assign a value to it using =.

      Loops in Go

      The file loops.go demonstrates loops in Go:

      ./loops.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      
      package main
      
      import (
          "fmt"
      )
      
      func main() {
          for loopIndex := 0; loopIndex < 20; loopIndex++ {
              if loopIndex%10 == 0 {
                  continue
              }
      
              if loopIndex == 19 {
                  break
              }
              fmt.Print(loopIndex, " ")
          }
          fmt.Println()
      
          // Use break to exit the for loop
          loopIndex := 10
          for {
              if loopIndex < 0 {
                  break
              }
              fmt.Print(loopIndex, " ")
              loopIndex--
          }
          fmt.Println()
      
          // This is similar to a while(true) do something loop
          loopIndex = 0
          anExpression := true
          for ok := true; ok; ok = anExpression {
              if loopIndex > 10 {
                  anExpression = false
              }
      
              fmt.Print(loopIndex, " ")
              loopIndex++
          }
          fmt.Println()
      
          anArray := [5]int{0, 1, -1, 2, -2}
          for loopIndex, value := range anArray {
              fmt.Println("index:", loopIndex, "value: ", value)
          }
      }
      • There are two types of for loops in Go. Traditional for loops that use a control variable initialization, condition, and afterthought; and those that iterate over the elements of a Go data type such as an array or a map using the range keyword.

      • Go has no direct support for while loops. If you want to use a while loop, you can emulate it with a for loop.

      • In their simplest form, for loops allow you to iterate, a predefined number of times, for as long as a condition is valid, or according to a value that is calculated at the beginning of the for loop. Such values include the size of a slice or an array, or the number of keys on a map. However, range is more often used for accessing all the elements of a slice, an array, or a map because you do not need to know the object’s cardinality in order to process its elements one by one. For simplicity, this example uses an array, and a later example will use a slice.

      • You can completely exit a for loop using the break keyword. The break keyword also allows you to create a for loop without an exit condition because the exit condition can be included in the code block of the for loop. You are also allowed to have multiple exit conditions in a for loop.

      • You can skip a single iteration of a for loop using the continue keyword.

      1. Execute the loops.go program:

        go run loops.go
        

        You will see the following output:

          
        1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18
        10 9 8 7 6 5 4 3 2 1 0
        0 1 2 3 4 5 6 7 8 9 10 11
        index: 0 value:  0
        index: 1 value:  1
        index: 2 value:  -1
        index: 3 value:  2
        index: 4 value:  -2
            
        

      Functions in Go

      Functions are first class citizens in Go, which means that functions can be parameters to other functions as well as returned by functions. This section will illustrate various types of functions.

      Go also supports anonymous functions. These can be defined inline without the need for a name and they are usually used for implementing operations that require a small amount of code. In Go, a function can return an anonymous function or take an anonymous function as one of its arguments. Additionally, anonymous functions can be attached to Go variables. In functional programming terminology anonymous functions are called closures. It is considered a good practice for anonymous functions to have a small implementation and a local focus.

      Regular functions

      This section will present the implementation of some traditional functions.

      ./functions.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      
      package main
      
      import (
          "fmt"
      )
      
      func doubleSquare(firstNum int) (int, int) {
          return firstNum * 2, firstNum * firstNum
      }
      
      func namedMinMax(firstNum, secondNum int) (min, max int) {
          if firstNum > secondNum {
              min = secondNum
              max = firstNum
          } else {
              min = firstNum
              max = secondNum
          }
          return
      }
      
      func minMax(firstNum, secondNum int) (min, max int) {
          if firstNum > secondNum {
              min = secondNum
              max = firstNum
          } else {
              min = firstNum
              max = secondNum
          }
          return min, max
      }
      
      func main() {
          secondNum := 10
      
          square := func(numberToSquare int) int {
              return numberToSquare * numberToSquare
          }
          fmt.Println("The square of", secondNum, "is", square(secondNum))
      
          double := func(numberToDouble int) int {
              return numberToDouble + numberToDouble
          }
          fmt.Println("The double of", secondNum, "is", double(secondNum))
      
          fmt.Println(doubleSquare(secondNum))
          doubledNumber, squaredNumber := doubleSquare(secondNum)
          fmt.Println(doubledNumber, squaredNumber)
      
          value1 := -10
          value2 := -1
          fmt.Println(minMax(value1, value2))
          min, max := minMax(value1, value2)
          fmt.Println(min, max)
          fmt.Println(namedMinMax(value1, value2))
          min, max = namedMinMax(value1, value2)
          fmt.Println(min, max)
      }
      • The main() function takes no arguments and returns no arguments. Once the special function main() exits, the program automatically ends.

      • The doubleSquare() function requires a single int parameter and returns two int values, which is defined as (int, int).

      • All function arguments must have a name – variadic functions are the only exception to this rule.

      • If a function returns a single value, you do not need to put parenthesis around its type.

      • Because namedMinMax() has named return values in its signature, the min and max parameters are automatically returned in the order in which they were put in the function definition. Therefore, the function does not need to explicitly return any variables or values in its return statement at the end, and does not. minMax() function has the same functionality as namedMinMax() but it explicitly returns its values demonstrating that both ways are valid.

      • Both square and double variables in main() are assigned an anonymous function. However, nothing stops you from changing the value of square, double, or any other variable that holds the result of an anonymous function, afterwards. This means that both variables may have a different value in the future.

      1. Execute the functions.go program.

        go run functions.go
        

        Your output will resemble the following:

          
        The square of 10 is 100
        The double of 10 is 20
        20 100
        20 100
        -10 -1
        -10 -1
        -10 -1
        -10 -1
            
        

      Variadic functions

      Variadic functions are functions that accept a variable number of arguments. The most popular variadic functions in Go can be found in the fmt package. The code of variadic.go illustrates the creation and the use of variadic functions.

      ./variadic.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      
      package main
      
      import (
          "fmt"
      )
      
      func varFunc(input ...string) {
          fmt.Println(input)
      }
      
      func oneByOne(message string, sliceOfNumbers ...int) int {
          fmt.Println(message)
          sum := 0
          for indexInSlice, sliceElement := range sliceOfNumbers {
              fmt.Print(indexInSlice, sliceElement, "t")
              sum = sum + sliceElement
          }
          fmt.Println()
          sliceOfNumbers[0] = -1000
          return sum
      }
      
      func main() {
          many := []string{"12", "3", "b"}
          varFunc(many...)
          sum := oneByOne("Adding numbers...", 1, 2, 3, 4, 5, -1, 10)
          fmt.Println("Sum:", sum)
          sliceOfNumbers := []int{1, 2, 3}
          sum = oneByOne("Adding numbers...", sliceOfNumbers...)
          fmt.Println(sliceOfNumbers)
      }
      • The ... operator used as a prefix to a type like ...int is called the pack operator, whereas the unpack operator appends a slice like sliceOfNumbers.... A slice is a Go data type that is essentially an abstraction of an array of unspecified length.

      • Each variadic function can use the pack operator once. The oneByOne() function accepts a single string and a variable number of integer arguments using the sliceOfNumbers slice.

      • The varFunc function accepts a single argument and just calls the fmt.Println() function.

      • Another note about slices: the second call to oneByOne() is using a slice. Any changes you make to that slice inside the variadic function will persist after the function exits because this is how slices work in Go.

      1. Execute the variadic.go program:

        go run variadic.go
        

        The output will resemble the following

          
        [12 3 b]
        Adding numbers...
        0 1     1 2     2 3     3 4     4 5     5 -1     6 10
        Sum: 24
        Adding numbers...
        0 1     1 2     2 3
        [-1000 2 3]
            
        

      Functions and pointer variables

      Go supports pointers and this section will briefly present how functions can work with pointers. A future Go guide will talk about pointers in more detail, but here is a brief overview.

      ./fPointers.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      
      package main
      
      import (
          "fmt"
      )
      
      func getPointer(varToPointer *float64) float64 {
          return *varToPointer * *varToPointer
      }
      
      func returnPointer(testValue int) *int {
          squareTheTestValue := testValue * testValue
          return &squareTheTestValue
      }
      
      func main() {
          testValue := -12.12
          fmt.Println(getPointer(&testValue))
          testValue = -12
          fmt.Println(getPointer(&testValue))
      
          theSquare := returnPointer(10)
          fmt.Println("sq value:", *theSquare)
          fmt.Println("sq memory address:", theSquare)
      }
      • The getPointer() function takes a pointer argument to a float64, which is defined as varToPointer *float64, where returnPointer() returns a pointer to an int, which is declared as *int.
      1. Execute the fPointers.go program:

        go run fPointers.go
        

        The output will resemble the following:

          
        146.8944
        144
        sq value: 100
        sq memory address: 0xc00001a0b8
            
        

      Functions with Functions as Parameters

      Go functions can have functions as parameters.

      ./fArgF.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      
      package main
      
      import "fmt"
      
      func doubleIt(numToDouble int) int {
          return numToDouble + numToDouble
      }
      
      func squareIt(numToSquare int) int {
          return numToSquare * numToSquare
      }
      
      func funFun(functionName func(int) int, variableName int) int {
          return functionName(variableName)
      }
      
      func main() {
          fmt.Println("funFun Double:", funFun(doubleIt, 12))
          fmt.Println("funFun Square:", funFun(squareIt, 12))
          fmt.Println("Inline", funFun(func(numToCube int) int { return numToCube * numToCube * numToCube }, 12))
      }
      • The funFun() function accepts two parameters, a function parameter named functionName and an int value. The functionName parameter should be a function that takes one int argument and returns an int value.

      • The first fmt.Println() call in main() uses funFun() and passes the doubleIt function, without any parentheses, as its first parameter.

      • The second fmt.Println() call uses funFun() with squareIt as its first parameter.

      • In the last fmt.Println() statement the implementation of the function parameter is defined inside the call to funFun() using an anonymous function.

      1. Execute the fArgF.go program:

        go run fArgF.go
        

        The output will resemble the following:

          
        function1: 24
        function2: 144
        Inline 1728
            
        

      Functions Returning Functions

      Go functions can return functions.

      ./fRetF.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
      package main
      
      import (
          "fmt"
      )
      
      func squareFunction() func() int {
          numToSquare := 0
          return func() int {
              numToSquare++
              return numToSquare * numToSquare
          }
      }
      
      func main() {
          square1 := squareFunction()
          square2 := squareFunction()
      
          fmt.Println("First Call to square1:", square1())
          fmt.Println("Second Call to square1:", square1())
          fmt.Println("First Call to square2:", square2())
          fmt.Println("Third Call to square1:", square1())
      }
      • squareFunction() returns an anonymous function with the func() int signature.

      • As squareFunction() is called two times, you will need to use two separate variables, square1 and square2 to keep the two return values.

      1. Execute the fRetF.go program:

        go run fRetF.go
        

        Your output will resemble the following:

          
        First Call to square1: 1
        Second Call to square1: 4
        First Call to square2: 1
        Third Call to square1: 9
            
        

        Notice that the values of square1 and square2 are not connected even though they both came from squareFunction().

      Errors in Go

      Errors and error handling are two important topics in Go. Go puts so much importance on error messages that it has a dedicated data type for errors, aptly named error. This also means that you can easily create your own error messages if you find that what Go gives you is not adequate. You will most likely need to create and handle your own errors when you are developing your own Go packages.

      Recognizing an error condition is one task, while deciding how to react to an error condition is another task. Therefore, some error conditions might require that you immediately stop the execution of the program, whereas in other error situations, you might just print a warning message and continue.

      ./errors.go
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      
      package main
      
      import (
          "errors"
          "fmt"
          "strconv"
      )
      
      func main() {
      
          customError := errors.New("My Custom Error!")
          if customError.Error() == "My Custom Error!" {
              fmt.Println("!!")
          }
      
          stringToConvert1 := "123"
          stringToConvert2 := "43W"
          _, err := strconv.Atoi(stringToConvert1)
          if err != nil {
              fmt.Println(err)
              return
          }
      
          _, err = strconv.Atoi(stringToConvert2)
          if err != nil {
              fmt.Println(err)
              return
          }
      }
      • The strconv.Atoi() function tries to convert a string into an integer, provided that the string is a valid integer, and returns two things, an integer value and an error variable. If the error variable is nil, then the conversion was successful and you get a valid integer. The _ character tells Go to ignore one, as in this case, or more of the return values of a function.

      • Most of the time, you need to check whether an error variable is equal to nil and then act accordingly. This kind of Go code is very popular in Go programs and you will see it and use it multiple times.

      • Also presented here is the errors.New() function that allows you to create a custom error message and errors.Error() function that allows you to convert an error variable into a string variable.

      1. Execute the errors.go program:

        go run errors.go
        

        Your output will resemble the following:

          
        !!
        strconv.Atoi: parsing "43W": invalid syntax
            
        

      Summary

      In this guide you learned the basics about the Go programming language, how to execute programs, how to write loops, how to handle errors, and you saw examples for various function types.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      Learning to Use the ss Tool to its Full Potential


      Updated by Linode

      Contributed by

      Mihalis Tsoukalos

      Introduction

      The study of socket connections is important for every
      UNIX and network administrator because it allows you to better understand your Linux system’s status. Written by Alexey Kuznetosv to replace the famous netstat utility , the more capable ss (socket statistics) utility allows you to monitor TCP, UDP, and UNIX sockets. The purpose of this guide is to help you learn the ss utility and to use it as productively as possible.

      Note

      Running ss without using the sudo utility will result in different output. Practically, this means that running ss without root privileges will show the results available to the current user only. If you are not familiar with the sudo command,
      see the Users and Groups guide.

      Command Line Options

      The ss(8) binary supports many command line options, including the following:

      Option Definition
      -h The -h option shows a summary of all options.
      -V The -V option displays the version of ss
      -H The -H option tells ss to suppress the header line – this is useful when you want to process the generated output using a scripting language.
      -t The -t parameter tells ss to show TCP connections only.
      -u The –u parameter tells ss to show UDP connections only.
      -d The –d parameter tells ss to show DCCP sockets only.
      -S The –S parameter tells ss to show SCTP sockets only.
      -a The -a option tells ss to display both listening and non-listening sockets of every kind.
      -l The -l parameter tells ss to display listening sockets, which are omitted by default.
      -e The -e option tells ss to display detailed socket information.
      -x The -x parameter tells ss to display UNIX domain sockets only.
      -A The -A option allows you to select the socket types that you want to see. The -A option accepts the following set of identifiers that can be combined and separated by commas: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram, unix_stream, unix_seqpacket, packet_raw and packet_dgram.
      -4 The -4 command line option tells ss to display IPv4 connections only.
      -6 The -6 command line option tells ss to display IPv6 connections only.
      -f FAMILY The -f tells ss to display sockets of type FAMILY. The supported values are unix, inet, inet6 and netlink.
      -s The -s option displays useful statistics about the current connections.
      -o The -o option displays timer information. There are five types of timers: on, which is either a TCP retrans timer, a TCP early retrans timer, or a tail loss probe timer; keepalive, which is the TCP keep alive timer; timewait, which is the timewait stage timer; persist, which is the zero window probe timer; and unknown, which is a timer that is none of the other timers.
      -n The -n option tells ss to disable the resolving of service names.
      -r The -r option tells ss to enable DNS resolving in the output, which is turned off by default.
      -m The -m parameter tells ss to display socket memory usage information.
      -p The -p parameter tells ss to display the process that is using a socket.
      -D FILE The -D parameter tells ss to save the output in the FILE file.

      Note

      The -A tcp option is equivalent to -t, the -A udp option is equivalent to -u and the –A unix
      option is equivalent to -x.

      Installing ss

      The ss tool is part of the IPROUTE2 Utility Suite. Since the ss command line tool is usually
      installed by default, you will not need to install it yourself. On a Debian Linux system, you can
      find the ss executable inside /bin.

      If for some reason ss is not installed on your Linux system, you should install the iproute2
      package using your favorite package manager.

      Examples

      Basic Usage

      The simplest way to use ss is without any command line parameters. When ss is
      used without any command line arguments, it prints all TCP, UDP and socket connections.
      The list might get big on busy machines, which means that it can become more difficult to parse – the output of wc(1), (a word count utility), shows that the list is long yet manageable:

      ss | wc
      
        
           94     750    7926
      
      

      If you also use the -a parameter to show all listening and non-listening sockets, the output will be much higher:

      ss -a | wc
      
        
          224    1682   19562
      
      

      Listing Sockets

      TCP

      The following command displays all listening and non-listening (-a) TCP (-t) sockets:

      ss -t -a
      
        
      State    Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
      LISTEN   0       80      127.0.0.1:mysql      *:*
      LISTEN   0       128     *:ssh                *:*
      LISTEN   0       100     *:smtp               *:*
      ESTAB    0       204     109.74.193.253:ssh   2.86.7.61:55137
      LISTEN   0       128     :::http              :::*
      LISTEN   0       128     :::ssh               :::*
      LISTEN   0       128     :::https             :::*
      
      

      The output is separated into columns. The first column, state, shows the state of the TCP connection. As the example is using the -a
      option, both listening and non-listening states are included in the output.
      The second and the third columns, Recv-Q and Send-Q, show the amount of data queued for receive and
      transmit operations. The Local Address:Port column shows the IP address the process
      listens to as well as the port number that is used – you can connect the name of the
      service with a numeric value by looking at the /etc/services file. The last column, Peer Address:Port, is useful when there is an active connection
      because it shows the address and port number of the client machine, though here it is without any real values for TCP connections that are in the
      LISTEN state.
      As the -r option is not used, you only see IP addresses in the output.

      Running ss -t without –a will display established TCP connections only:

      ss -t
      
        
      State  Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      ESTAB  0       204     109.74.193.253:ssh  2.86.7.61:55137
      
      

      UDP

      The following command displays all UDP (-u) sockets:

      ss -u -a
      
        
      State    Recv-Q  Send-Q  Local Address:Port                  Peer Address:Port
      UNCONN   0       0       *:mdns                              *:*
      UNCONN   1536    0       109.74.193.253:syslog               *:*
      UNCONN   0       0       *:54087                             *:*
      UNCONN   0       0       *:bootpc                            *:*
      UNCONN   0       0       109.74.193.253:ntp                  *:*
      UNCONN   0       0       127.0.0.1:ntp                       *:*
      UNCONN   0       0       *:ntp                               *:*
      UNCONN   0       0       :::mdns                             :::*
      UNCONN   0       0       :::48582                            :::*
      UNCONN   0       0       fe80::f03c:91ff:fe69:1381%eth0:ntp  :::*
      UNCONN   0       0       2a01:7e00::f03c:91ff:fe69:1381:ntp  :::*
      UNCONN   0       0       ::1:ntp                             :::*
      UNCONN   0       0       :::ntp                              :::*
      
      

      Running ss -u without –a will display established UDP connections only. In this case there are no established UDP connections:

      ss -u
      
        
      Recv-Q Send-Q  Local Address:Port  Peer Address:Port
      
      

      Display Statistics

      You can display statistics about the current connections using the -s option:

      ss -s
      
        
      Total: 199 (kernel 228)
      TCP:   9 (estab 1, closed 2, orphaned 0, synrecv 0, timewait 0/0), ports 0
      
      Transport  Total  IP  IPv6
      *          228    -   -
      RAW        0      0   0
      UDP        13     7   6
      TCP        7      4   3
      INET       20     11  9
      FRAG       0      0   0
      
      

      Filter by TCP State

      ss allows you to filter its output by state using the state and exclude keywords
      followed by a state identifier. The state keyword displays output that matches the
      provided identifier, whereas the exclude keyword displays everything except the output
      that matches the identifier.

      The use of state is illustrated in the next example:

      ss -t4 state established
      
        
      Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      0       0       109.74.193.253:ssh  2.86.7.61:55137
      
      

      The use of exclude is illustrated in the next example:

      ss -t4 exclude established
      
        
      State      Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
      LISTEN     0       80      127.0.0.1:mysql      *:*
      LISTEN     0       128     *:ssh                *:*
      LISTEN     0       100     *:smtp               *:*
      TIME-WAIT  0       0       109.74.193.253:smtp  103.89.91.73:55668
      
      

      The -t4 command option returns IPv4 TCP connections.

      Filter Output by IP Address and Port Number

      The more you filter the output of ss, the more accurate and relevant information you will receive. There exist two ss options that allow
      you to include connections from certain IP addresses and port numbers.

      The following command shows traffic from a given IP address only, using the
      dst keyword:

      ss -nt dst 2.86.7.61
      
        
      State        Recv-Q  Send-Q  Local Address:Port         Peer Address:Port
      ESTAB        0      0        109.74.193.253:22          2.86.7.61:55137
      FIN-WAIT-1   0       32      ::ffff:109.74.193.253:443  ::ffff:2.86.7.61:56075
      ESTAB        0       0       ::ffff:109.74.193.253:443  ::ffff:2.86.7.61:56077
      ESTAB        0       0       ::ffff:109.74.193.253:443  ::ffff:2.86.7.61:56074
      ESTAB        0       0       ::ffff:109.74.193.253:443  ::ffff:2.86.7.61:56078
      
      

      If you want to display traffic from an entire network, you can replace the IP address with
      a network address such as 2.86.7/24.

      The following command displays information about the HTTP and the HTTPS protocols, which
      are associated with port numbers 80 and 443 as defined in /etc/services:

      ss -at '( dport = :http or dport = :https or sport = :http or sport = :https )'
      
        
      State      Recv-Q  Send-Q  Local Address:Port           Peer Address:Port
      LISTEN     0       128     :::http                      :::*
      LISTEN     0       128     :::https                     :::*
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56046
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56055
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56047
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56054
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56056
      ESTAB      0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:56057
      TIME-WAIT  0       0       ::ffff:109.74.193.253:http   ::ffff:54.39.151.52:59854
      
      

      dport means destination port and sport means source port.

      The following command is equivalent to the previous command:

      ss -at '( dport = :80 or dport = :443 or sport = :80 or sport = :443 )'
      

      Display Timer Information

      The -o option displays timer information:

      ss -nt dst 2.86.7.61 -o
      
        
      State  Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      ESTAB  0       0       109.74.193.253:22   2.86.7.61:55137     timer:(keepalive,72min,0)
      
      

      Enable IP Address Resolving

      The -r parameter enables IP address resolving, which returns the domain names of the IP addresses:

      ss -r -t
      
        
      State  Recv-Q  Send-Q    Local Address:Port                  Peer Address:Port
      ESTAB  0       168       li140-253.members.linode.com:ssh    ppp-2-86-7-61.home.otenet.gr:50939
      ESTAB  0       0         li140-253.members.linode.com:https  ::ffff:216.244.66.228:37668
      
      

      Note

      A side effect of the -r command line option is that it slows the execution of
      the ss command due to the DNS lookups that need to be performed.

      Display Detailed Socket Information

      The -e option tells ss to display detailed socket information. The -e option
      is illustrated in the following example:

      ss -t -e
      
        
      State  Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      ESTAB  0       0       109.74.193.253:ssh  2.86.7.61:62897    timer:(keepalive,54min,0) ino:10195329 sk:11e 
      
      

      Show a Connection’s UNIX Process

      The -p option displays the process ID(s) and the process name of a connection:

      ss -t -p
      
        
      State  Recv-Q  Send-Q  Local Address:Port           Peer Address:Port
      ESTAB  0       204     109.74.193.253:ssh           2.86.7.61:55137            users:(("sshd",pid=3964,fd=3),("sshd",pid=3951,fd=3))
      ESTAB  0       51      ::ffff:109.74.193.253:https  ::ffff:176.9.146.74:57536  users:(("apache2",pid=30871,fd=29))
      
      

      The following command shows SSH-related processes on the current machine:

      ss -t -p -a | grep ssh
      
        
      LISTEN  0  128  *:ssh               *:*                    users:(("sshd",pid=812,fd=3))
      ESTAB   0  36   109.74.193.253:ssh  2.86.7.61:55137        users:(("sshd",pid=3964,fd=3),("sshd",pid=3951,fd=3))
      ESTAB   0  0    109.74.193.253:ssh  138.197.140.194:41992  users:(("sshd",pid=8538,fd=3),("sshd",pid=8537,fd=3))
      LISTEN  0  128  :::ssh              :::*                   users:(("sshd",pid=812,fd=4))
      
      

      Find Which Process is Using a Given Port Number

      With the help of ss and grep(1), you can discover which process is using
      a given port number:

      ss -tunap | grep :80
      
        
      tcp  LISTEN  0  128  :::80 :::*  users:(("apache2",pid=8772,fd=4),("apache2",pid=8717,fd=4),("apache2",pid=8715,fd=4),("apache2",pid=8714,fd=4),("apache2",pid=8713,fd=4),("apache2",pid=8712,fd=4),("apache2",pid=8711,fd=4),("apache2",pid=8709,fd=4))
      
      

      As Apache uses multiple child processes, you receive a list of processes for port number 80.

      The next command will do exactly the same thing without using grep(1):

      ss -tup -a sport = :80
      
        
      Netid  State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      tcp    LISTEN  0       128     :::http             :::*               users:(("apache2",pid=8715,fd=4),("apache2",pid=8714,fd=4),("apache2",pid=8713,fd=4),("apache2",pid=8712,fd=4),("apache2",pid=8711,fd=4),("apache2",pid=8709,fd=4))
      
      

      Find Open Ports Above Port Number 1024

      ss supports ranges when working with port numbers. This feature is illustrated in
      the following example that finds open port above port number 1024:

      ss -t -a sport > :1024
      
        
      State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      LISTEN  0       80      127.0.0.1:mysql     *:*
      
      

      Note

      The ss -t -a sport > :1024 command can be also written as ss -t -a sport '> :1024'.

      Search for Specific TCP Characteristics

      The following command shows all TCP connections that use IPv4 that are in
      listening state, as well as the name of the process using the socket without
      resolving the IP addresses and the port number:

      ss -t -4nlp
      
        
      State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      LISTEN  0       80      127.0.0.1:3306      *:*                users:(("mysqld",pid=1003,fd=17))
      LISTEN  0       128     *:22                *:*                users:(("sshd",pid=812,fd=3))
      LISTEN  0       100     *:25                *:*                users:(("smtpd",pid=9011,fd=6),("master",pid=1245,fd=13))
      
      

      The following command shows all SSH related connections and sockets:

      ss -at '( dport = :ssh or sport = :ssh )'
      
        
      State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      LISTEN  0       128     *:ssh               *:*
      ESTAB   0       0       109.74.193.253:ssh  2.86.7.61:64363
      LISTEN  0       128     :::ssh              :::*
      
      

      Show Sockets in a Listening State

      The following command shows TCP sockets in listening (-l) state:

      ss -l -t
      
        
      State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port
      LISTEN  0       80      127.0.0.1:mysql     *:*
      LISTEN  0       128     *:ssh              *:*
      LISTEN  0       100     *:smtp              *:*
      LISTEN  0       128     :::http             :::*
      LISTEN  0       128     :::ssh              :::*
      LISTEN  0       128     :::https            :::*
      
      

      The following command shows IPv4 UDP sockets in listening state:

      ss -l -u -4
      
        
      State   Recv-Q  Send-Q  Local Address:Port      Peer Address:Port
      UNCONN  0       0       *:mdns                  *:*
      UNCONN  1536    0        109.74.193.253:syslog  *:*
      UNCONN  0       0        *:54087                *:*
      UNCONN  0       0        *:bootpc               *:*
      UNCONN  0       0        109.74.193.253:ntp     *:*
      UNCONN  0       0        127.0.0.1:ntp          *:*
      UNCONN  0       0        *:ntp                  *:*
      
      

      Advanced Filtering with ss

      The following ss command will list all TCP sockets that are in the ESTABLISHED state, use HTTP or HTTPS on the local machine and belong to the 2.86.7/24 network and display their timers:

      ss -o state established '( sport = :http or sport = :https )' dst 2.86.7/24
      
        
      Netid  Recv-Q  Send-Q  Local Address:Port           Peer Address:Port
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63057  timer:(keepalive,119min,0)
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63053  timer:(keepalive,119min,0)
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63055  timer:(keepalive,119min,0)
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63054  timer:(keepalive,119min,0)
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63052  timer:(keepalive,119min,0)
      tcp    0       0       ::ffff:109.74.193.253:https  ::ffff:2.86.7.61:63056  timer:(keepalive,119min,0)
      
      

      Apart from the standard TCP state names (established,
      syn-sent, syn-recv, fin-wait-1, fin-wait-2, time-wait, closed, close-wait, last-ack,
      listen and closing), you can also use the following states:

      • all: For all the states.
      • bucket: For TCP minisockets (TIME-WAIT|SYN-RECV) states.
      • big: For all states except for minisockets – this is the opposite of bucket.
      • connected: For the not closed and not listening states.
      • synchronized: For connected and not SYN-SENT states.

      Using AWK to Process ss Output

      The following command displays a summary of all sockets based on their state:

      ss -t -u -a | awk '{print $1}' | grep -v State | sort | uniq -c | sort -nr
      
        
           13 udp
            7 tcp
            1 Netid
      
      

      The following command displays a summary of all sockets based on their protocol:

      ss -a | awk '{print $1}' | grep -v State | sort | uniq -c | sort -nr
      
        
          133 u_str
           37 u_dgr
           34 nl
           13 udp
            8 tcp
            1 u_seq
            1 p_raw
            1 Netid
      
      

      The last command will create a summary of all IPv6 TCP connections that are in
      the CONNECTED state:

      ss -t6 state connected | awk '{print $1}' | grep -v State | sort | uniq -c | sort -nr
      

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      Learning to Use netcat to its Full Potential


      Updated by Linode

      Contributed by

      Mihalis Tsoukalos

      Netcat is a simple but handy UNIX utility that reads and writes data across network connections, using either TCP or UDP. The purpose of this guide is to help you learn the netcat command line utility and use it productively.

      Before You Begin

      Some of the commands in this guide will require the use of two terminal windows running netcat, one acting as a server and the other as the client. These can be separate machines, or you can connect to the same localhost.

      Note

      This guide is written for a non-root user. Depending on your configuration, some commands might require the help of sudo in order to get property executed. If you are not familiar with the sudo command, see the Users and Groups guide.

      Port numbers 0-1024 are restricted and can only be used with root privileges, which means that you should use the sudo command for creating TCP/IP servers that use port numbers 0-1024.
      This rule does not apply to TCP/IP clients that use port numbers 0-1024.

      Introduction

      As netcat is not installed by default, you will most likely need to install netcat on
      your Linux machine using your favourite package manager.

      Note

      The netcat binary usually has an alias named nc, which is what will be used
      in this guide because it is shorter. Usually both commands point to the same binary file.

      If you execute apt-cache search netcat on a Debian machine, you will see the following output:

      apt-cache search netcat
      
        
      netcat - TCP/IP swiss army knife -- transitional package
      netcat-traditional - TCP/IP swiss army knife
      netcat-openbsd - TCP/IP swiss army knife
      
      

      Notice that netcat is a dummy package and its purpose is to ease upgrades. The
      differences between the other two packages are not big, but you will need to visit
      their package descriptions and their man pages in order to get a detailed description
      of their capabilities.

      The OpenBSD version of netcat supports IPv6, proxies and UNIX sockets, which are not
      supported by the netcat-traditional variant. On the other hand, netcat-traditional includes
      support for the -e option that allows you to execute a program from a remote shell, which is
      not offered by netcat-openbsd. However, if you do not need any of these features, you will
      not notice any real difference between these two versions of netcat.

      This guide will be using the netcat binary that comes with the netcat-traditional package.
      This version of netcat was written by a person known as Hobbit.

      Command Line Options

      netcat commands have the netcat [options] host port generic form. The nc binary
      supports the following command line options:

      Option Usage
      -u The -u option tells nc to work in UDP mode. If -u is not present, nc will be using TCP.
      -l The -l option tells nc to listen for incoming connections, which makes it a server process.
      -h The -h option displays a help screen.
      -e filename The -e option tells nc to execute the a file named with the filename parameter after a client connection.
      -c string The -c option tells nc to pass the contents of string to /bin/sh -c for execution after a client connection.
      -i seconds The -i option defines the delay interval used by nc when sending lines or scanning ports.
      -q seconds The -q option tells nc to wait the specified number of seconds before quitting after getting an EOF in standard input. If the value is negative, nc will wait forever.
      -v The -v option tells nc to produce verbose output.
      -vv The -vv option tells nc to produce even more verbose output than the -v option.
      -z The -z option tells nc to use zero-I/O mode, which is used when performing port scanning.
      -r The -r option tells nc to use random local and remote ports, which might be good for testing.
      -o file The -o option tells nc to save the hex dump of network traffic to file, which might be handy for debugging.
      -n The -n option tells nc to use IP addresses (numeric) only.
      -p port The -p option tells nc which port number to use.
      -b The -b option tells nc to allow UDP broadcasts.
      -C The -C option tells nc to send CRLF as line-ending.
      -T type The -T option allows nc to set the type of the TOS (Type Of Service) flag.
      -g gateway The -g option allows you to specify the route that the packets will take through the network. You can learn more about Source Routing here.
      -G number The value of the -G option allows you to specify the value of the source routing pointer. You can learn more about the Source Routing pointer here.
      -s address The -s option allows you to specify the local source address that will be used in the nc command.
      -t The -t option is used for enabling telnet negotiation.

      The remainder of this guide will demonstrate the most important of these commands. That being said, netcat is a versatile tool, and there’s a large opportunity for experimenting on your own.

      Using netcat as a Client

      The most common use of netcat is to act as a client for a server process. This is mostly
      used for troubleshooting network servers and network connections because you can see the raw data
      of the interaction. So, providing nc with just a hostname or IP address and a port number
      will make netcat act as the telnet utility:

      nc localhost 22
      
        
      SSH-2.0-OpenSSH_7.9p1 Debian-10
      
      

      In the given example, nc tries to connect to TCP port number 22 of the localhost – notice
      that TCP port number 22 is used by SSH, which is what triggers the provided output.

      Also notice that as the -u option is not used, nc will use the TCP protocol by default.

      Using netcat as a Server

      nc will accept connections at a given port and act as a server when you execute
      it with the -l option:

      nc -l -p 1234
      

      In another terminal window, connect a client to the server with nc:

      nc 127.0.01 1234
      

      You can now send messages between the two machines with nc.

        
      This is a client!
      Hello from the server!
      
      

      The previous command tells netcat to listen on TCP port number 1234 for incoming
      connections – you can also see that netcat automatically reads data from the client
      and that you can send your response to the TCP client just by typing it.

      Once again, as the -u option is not used, nc will use the TCP protocol.

      Getting Verbose Output

      There are times where you cannot connect to the remote machine or the answer you get is
      not the expected one. In such cases, it is good to use either -v or -vv in order to
      get more information from the nc connection.

      nc -v localhost 1234
      
        
      localhost [127.0.0.1] 1234 (?) : Connection refused
      
      

      The output you get shows that the reason you cannot connect to localhost
      using TCP port number 1234 is that your connection was refused by the server.
      Executing nc localhost 1234 will return no output, which offers no help.

      Using -vv instead of -v will generate the following kind of output:

      nc -vv localhost 1234
      
        
      localhost [127.0.0.1] 1234 (?) : Connection refused
       sent 0, rcvd 0
      
      

      If the TCP connection was successful, you would have gotten the following kind of
      output on the client side:

      nc -vv localhost 1234
      
        
      localhost [127.0.0.1] 1234 (?) open
      
      

      Both -v and -vv are very valuable when things do not work as expected.

      Using the UDP Protocol

      In order to use the UDP protocol instead of the TCP protocol, you should include
      the -u option in your nc commands. Therefore, the following command will
      use the UDP protocol:

      nc –vv –u 8.8.8.8 53
      
        
      dns.google [8.8.8.8] 53 (domain) open
      
      

      As we are trying to connect to a (public) DNS server, we will have to use port number 53.

      Examples

      In this section you will find a number of use cases and examples for nc.

      Using netcat for Port Scanning

      Netcat can be used for port scanning as a naive version of nmap with the -z option. The command that follows scans the localhost, which has an IP address of 127.0.0.1, using a range of port numbers from 1 to 30 (1-30):

      netcat -z -vv -n 127.0.0.1 1-30
      
        
      (UNKNOWN) [127.0.0.1] 30 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 29 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 28 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 27 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 26 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 25 (smtp) open
      (UNKNOWN) [127.0.0.1] 24 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 23 (telnet) : Connection refused
      (UNKNOWN) [127.0.0.1] 22 (ssh) open
      (UNKNOWN) [127.0.0.1] 21 (ftp) : Connection refused
      (UNKNOWN) [127.0.0.1] 20 (ftp-data) : Connection refused
      (UNKNOWN) [127.0.0.1] 19 (chargen) : Connection refused
      (UNKNOWN) [127.0.0.1] 18 (msp) : Connection refused
      (UNKNOWN) [127.0.0.1] 17 (qotd) : Connection refused
      (UNKNOWN) [127.0.0.1] 16 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 15 (netstat) : Connection refused
      (UNKNOWN) [127.0.0.1] 14 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 13 (daytime) : Connection refused
      (UNKNOWN) [127.0.0.1] 12 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 11 (systat) : Connection refused
      (UNKNOWN) [127.0.0.1] 10 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 9 (discard) : Connection refused
      (UNKNOWN) [127.0.0.1] 8 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 7 (echo) : Connection refused
      (UNKNOWN) [127.0.0.1] 6 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 5 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 4 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 3 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 2 (?) : Connection refused
      (UNKNOWN) [127.0.0.1] 1 (tcpmux) : Connection refused
       sent 0, rcvd 0
      
      

      Notice that as we are using the -n option, the server should be specified by its
      IP address. Additionally, if you omit the -vv option, you will get a much shorter
      output, which is verified by the following output:

      nc -z -v -n 127.0.0.1 1-30
      
        
      (UNKNOWN) [127.0.0.1] 25 (smtp) open
      (UNKNOWN) [127.0.0.1] 22 (ssh) open
      
      

      Therefore, the use of -v makes nc to display open TCP ports only.

      If you do not use -v or -vv, the previous command will return no output:

      nc -z -n 127.0.0.1 1-30
      
        
      
      

      Using netcat for Transferring Files

      One of the features of netcat is that it is capable of transferring files:

      cat access.log | nc -vv -l -p 4567
      
        
      listening on [any] 4567 ...
      connect to [127.0.0.1] from localhost [127.0.0.1] 53952
      
      

      When a client connects to TCP port number 4567, nc will send the contents of the
      access.log file to it. The correct way to execute a nc client in order to get that
      file is the following. Open a new terminal window and enter this command:

      nc -vv localhost 4567 > fileToGet
      
        
      localhost [127.0.0.1] 4567 (?) open
      ^C sent 0, rcvd 362148
      
      

      You will need to press Control+C for the TCP connection to close.

      Using netcat for Making any Process a Server

      Netcat allows you to make any process a server process with the help of the –e parameter:

      nc -vv -l -p 12345 -e /bin/bash
      
        
      listening on [any] 12345 ...
      connect to [127.0.0.1] from localhost [127.0.0.1] 46930
      bash: line 2: asd: command not found
      
      

      Here you tell nc to accept incoming TCP connections on TCP port number 12345. When
      a connection is accepted, nc will execute /bin/bash, which means that it will give
      you shell access on the machine. After a client successfully connects, every input line
      will be executed as a shell command using /bin/bash. If the command cannot be found,
      the client will get no output and an error message will be generated on the server side.
      Otherwise, the output of the command will be sent to the client. To test this functionality, in another terminal window create a nc client and type in the following command:

      nc localhost 12345
      

      Caution

      This capability of netcat can introduce security threats on your Linux machine
      when used improperly. It is advised that you exercise caution if using this feature.

      Executing a Command After Connecting

      If you want to execute a given command each time a client connects to a server that is
      implemented using nc, then you should use the -c option followed by that command.
      The example that follows executes ls -l and sends the output to the client:

      nc -vv -c "ls -l" -l 127.0.0.1 -p 1234
      
        
      listening on [any] 1234 ...
      connect to [127.0.0.1] from localhost [127.0.0.1] 33788
      
      

      Try executing nc 127.0.0.1 1234 on another terminal on your local machine to get the
      output of ls -l.

      Caution

      This capability of netcat can introduce security threats on your Linux machine
      when used improperly. It is advised that you exercise caution if using this feature.

      Using netcat as a Simple Web Server

      Let us say that you want to serve a simple HTML page, which in this case will be called
      index.html, from your Linux machine but you have no real web server available. You can
      use netcat to serve that simple HTML page on clients from your local machine as follows:

      nc -vv -l 127.0.0.1 -p 4567 < index.html
      

      Using wget to get that page will generate the following output in the nc part:

        
      listening on [any] 4567 ...
      connect to [127.0.0.1] from localhost [127.0.0.1] 53980
      GET / HTTP/1.1
      User-Agent: Wget/1.18 (linux-gnu)
      Accept: */*
      Accept-Encoding: identity
      Host: localhost:4567
      Connection: Keep-Alive
      
      

      Additionally, when using wget, we will receive the following output, which reflects the contents
      of the index.html page:

      wget -qO- http://localhost:4567/
      
        
      <title>Page Under Construction</title>
      <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
      <style type="text/css">
      body {
        background-color:#000;
      }
      .img {
        margin:180px 50px 75px 450px;
      }
      </style>
      </head>
      <body>
          <H1>Under Construction</H1>
      </body>
      </html>
      
      

      Using netcat for Getting Data from Web Servers

      The HTTP service is just a TCP service; therefore nc can be used for getting data from
      a web server or for testing web servers. The following command will connect to the
      www.linode.com machine using port number 80, which corresponds to the HTTP protocol:

      nc www.linode.com 80
      

      You should type the first line (GET / HTTP/1.1) and press the enter key two times
      in order to get a response from the web server.

        
      GET / HTTP/1.1
      
      HTTP/1.1 400 Bad Request
      Server: nginx
      Date: Wed, 10 Jul 2019 20:02:47 GMT
      Content-Type: text/html
      Content-Length: 166
      Connection: close
      
      <html>
      <head><title>400 Bad Request</title></head>
      <body bgcolor="white">
      <center><h1>400 Bad Request</h1></center>
      <hr><center>nginx</center>
      </body>
      </html>
      
      

      A better way to execute this command is the following:

      echo -en "GET / HTTP/1.0nnn" | netcat www.linode.com 80
      
        
      HTTP/1.1 301 Moved Permanently
      Server: nginx
      Date: Wed, 10 Jul 2019 20:04:10 GMT
      Content-Type: text/html
      Content-Length: 178
      Connection: close
      Location: https:///
      
      <html>
      <head><title>301 Moved Permanently</title></head>
      <body bgcolor="white">
      <center><h1>301 Moved Permanently</h1></center>
      <hr><center>nginx</center>
      </body>
      </html>
      
      

      This used to be a very popular way of testing web servers when every web server
      was using the HTTP protocol. Nowadays, the use of HTTPS makes difficult to test
      a web server using tools such as netcat and telnet because the web traffic is
      encrypted.

      Using netcat for Creating a Chat Server

      Creating a basic chat server with nc for two machines to communicate with each other is completed in two commands. One of the machines will function as the server and the other machine will be the client. On the server you will need to execute the following:

      nc -vv -l 127.0.0.1 -p 1234
      
        
      listening on [any] 1234 ...
      connect to [127.0.0.1] from localhost [127.0.0.1] 60608
      Hello!
      
      

      And on the client:

      nc -vv 127.0.0.1 1234
      
        
      Hello!
      
      

      If both people that want to talk are on the same Linux machine, then using 127.0.0.1 is
      safer and quicker. Otherwise, you should use the IP address of the server in both commands.

      Transferring Entire Directories Using netcat

      This section will explain how to transfer entire directories using netcat. Imagine that you wish to transfer the var directory that resides under
      your home directory. You can do that as follows:

      tar -cvf - ~/var | nc -vv -l 127.0.0.1 -p 1234
      
        
      listening on [any] 1234 ...
      tar: Removing leading `/' from member names
      /home/username/var/
      /home/username/var/slide.tar.ORG
      
      

      This creates a TCP server that listens on TCP port number 1234
      on the host with the 127.0.0.1 IP address. Generally speaking, using 127.0.0.1
      as the server IP address is more secure than using one of the real IP addresses of
      your Linux machine provided that both the server and the client are on the same
      Linux machine.

      After that you will need to execute the following command on the client side:

      cd /tmp
      nc 127.0.0.1 1234 | tar -xvf -
      
        
      home/username/var/
      home/username/var/slide.tar.ORG
      home/username/var/after.tshark
      home/username/var/test.pcap
      home/username/var/sys09725827.php
      home/username/var/test.php
      home/username/var/u5EJqp.php
      home/username/var/http.pcap
      home/username/var/sketch.zip
      
      

      When the client connects, the nc server will also print the following output:

        
      listening on [any] 1234 ...
      tar: Removing leading `/' from member names
      /home/username/var/
      /home/username/var/slide.tar.ORG
      connect to [127.0.0.1] from localhost [127.0.0.1] 60632
      /home/username/var/after.tshark
      /home/username/var/test.pcap
      /home/username/var/sys09725827.php
      /home/username/var/test.php
      /home/username/var/u5EJqp.php
      /home/username/var/http.pcap
      /home/username/var/sketch.zip
       sent 3645440, rcvd 0
      
      

      You will need to press Control+C for the TCP connection to close.

      Testing the Network Speed Using netcat

      This section will explain how to test the connection speed between
      two machines using nc. You will need two hosts. On the server machine use the following command:

      time nc -vv -n -l -p 2222 >/dev/null
      
        
      listening on [any] 2222 ...
      connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 42286
       sent 0, rcvd 2090934272
      
      real	0m21.438s
      user	0m0.230s
      sys	0m1.190s
      
      

      On the client machine, you should execute the following command and press Control+C
      after the desired amount of time to end the connection:

      time yes | nc.traditional -vv -n 127.0.0.1 2222 >/dev/null
      
        
      (UNKNOWN) [127.0.0.1] 2222 (?) open
      ^C sent 2090926080, rcvd 0
      
      
      real	0m5.482s
      user	0m0.456s
      sys	0m3.109s
      
      

      Now that you know it took 5.482s to transfer 2090926080 bytes, you can calculate the network speed. As the nc server starts first, you should use the numbers found in the nc client.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link