The task:

Output the IP address under which the machine sends requests to 8.8.8.8 (there is no need to take into account NAT after the packet leaves the machine, you need an IP address with which the packet leaves the machine).

You need to write a bash script. As I understand it, you need to understand where we have a gateway on the local network.

At the moment, the following is ready:

use tcpdump - tcpdump -i any 'udp port 53'> whoIP - so the dump result with all requests for port 53 (that is, DNS) is saved to a file.

The file contains the following lines:

15: 09: 44.365818 IP 192.168.0.102.11996> 192.168.0.1.domain: 31675+ A? www.google-analytics.com. (42)

15: 09: 44.398267 IP 192.168.0.1.domain> 192.168.0.102.11996: 31675 7/0/0 CNAME www-google-analytics.l.google.com., A

then using the "Hellish" expression: cat whoIP | grep A? | grep -E -o '> + ([0-9] {1,3} [.]) {3} [0-9] {1,3}' | grep -E -o "([0-9] {1,3} [.]) {3} [0-9] {1,3}"

Its logic is as follows:

  1. cat whoIP | grep A? - in the file we are looking for lines containing a request for name resolution. tcpdump marks such strings as A?

  2. | grep -E -o '> + ([0-9] {1,3} [.]) {3} [0-9] {1,3}' - this regular expression searches for an IP address in ipv4 format. in the line we are looking for the following construction ">" ipv4 address "" - in tcpdump ">" means from whom to whom the request goes. We are interested in who.

  3. | grep -E -o "([0-9] {1,3} [.]) {3} [0-9] {1,3}" - from the found fragment "to whom" we cut out only the address. This expression from previous differs only in the absence of "<"

    In general, my algorithm is as follows:

1. Run tcpdump and redirect its output to the whoIP file

  1. Send another DNS request to another terminal with dig

  2. STOP TCPDUMP ctrl + c

  3. grep file

Firstly, the problem is that I can’t put this sequence in the script, because tcpdump works until it sends a termination signal (here is a snag). If the script is looking to start tcpdump, then the following commands are not executed, because tcpdump works endlessly.

Tell me, is it possible to write this script, and in general, am I going the right way, which I doubt very much. It seems to me that there should be a simpler solution.

  • Here look at the selected answer. - Alekcvp

2 answers 2

If it works, then it has the right to life. And tcpdump can be made to work as needed.

first you need to run it in the background

tcpdump .... параметры .... & 

The & symbol is important - it sends the process to the background and you can continue the script further.

Since we will need to stop it later, the next line is to memorize its pid.

 TDPID=$! 

This line should be immediately. Otherwise, it will remember another PID. TDPID is just a variable.

insert your code further. When you need to stop tcpdump, just send it Ctrl + C

 kill -3 $TDPID 

PS An important point that everyone stumbles upon and for a long time cannot understand what is wrong. In the line TDPID=$! There should be no spaces. If you write the TDPID = $! , it will not work.

  • Thanks for the advice, I tried, but there was a new problem - tcpdump, becoming a background process, does not write to the file with ">". Also, the process does not end with the kill -3 command, only with the kill -2 command - Mr.Ki.D.
  • one
    You can use the -w flag, which allows you to save to a file. True in binary pcap format. This file can then be "played" with the same tcpdump via the -r option - KoVadim

It seems to me that there should be a simpler solution.

quite right. if we are talking about the network subsystem of the linux program, the version is higher or equal to 2.0 (or 2.1 ? I can’t remember), you can use the ip program:

 $ ip route get 8.8.8.8 8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.2 cache 

in the example output, 192.168.0.2 - this is the ip-address with which the packets addressed to 8.8.8.8 will leave the system.

if the full output of the program is not suitable, and this address must be extracted, then for convenience of processing, you can add the option -o ( oneline ):

 $ ip -o route get 8.8.8.8 8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.2 \ cache 

and extract it using, for example, the sed program (by the way, the route and get parameters in this case can be reduced to one letter):

 $ ip -org 8.8.8.8 | sed 's/.*src \([^ ]\+\) .*/\1/' 192.168.0.2 

for details, see the documentation for the ip program: man ip , man ip-route .


By the way, there may be more than one route (for example, when using dynamic routing on a given machine). they will all be displayed, and, therefore, in the final output there will be more than one line with ip-addresses.