Skip to content

Commit dcf11e1

Browse files
committed
Merge PR #46: Add container name resolution
2 parents b5f9c3f + c87cb89 commit dcf11e1

10 files changed

Lines changed: 979 additions & 6 deletions

File tree

EXAMPLES.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,95 @@ hexadecimal form.
364364
As it turns out, several other packets also matched this pattern, but this
365365
should give you a good idea of how to use hexadecimal patterns and the hex
366366
output mode.
367+
368+
## Container name resolution (Docker / Podman)
369+
370+
When running ngrep on a host that has Docker or Podman containers, raw IP
371+
addresses on a bridge network are essentially meaningless -- they're ephemeral
372+
and change on every `docker-compose up`. Pass `-r` to resolve container IPs to
373+
their names, making the output immediately readable.
374+
375+
Container resolution is compiled in by default (disable at build time with
376+
`--disable-container-resolution` if needed).
377+
378+
If the Docker (or Podman) socket is accessible, ngrep uses the Events API for
379+
real-time tracking -- new containers show up the instant they start, and dead
380+
ones are purged immediately. If the socket isn't available (e.g. rootless
381+
Podman, permission issues), it falls back to CLI-based polling with a
382+
30-second cache TTL.
383+
384+
### Debugging microservice traffic
385+
386+
Suppose you have a typical compose stack -- an API gateway, an auth service,
387+
and a Postgres database. Without container resolution, you'd see something
388+
like:
389+
390+
```
391+
# ngrep -d docker0 -W byline port 5432
392+
T 172.18.0.4:48120 -> 172.18.0.2:5432 [AP]
393+
...
394+
T 172.18.0.2:5432 -> 172.18.0.4:48120 [AP]
395+
...
396+
```
397+
398+
With `-r`, the same capture becomes:
399+
400+
```
401+
# ngrep -r -d docker0 -W byline port 5432
402+
container: using docker socket for real-time events
403+
T api_gateway(172.18.0.4):48120 -> postgres_db(172.18.0.2):5432 [AP]
404+
...
405+
T postgres_db(172.18.0.2):5432 -> api_gateway(172.18.0.4):48120 [AP]
406+
...
407+
```
408+
409+
No more cross-referencing `docker inspect` output.
410+
411+
### Watching HTTP traffic across a compose stack
412+
413+
* `ngrep -r -d br-a1b2c3 -W byline -q 'GET|POST' port 80`
414+
415+
Monitor all HTTP traffic on a Docker Compose bridge network. Each request
416+
shows which container is talking to which, e.g.:
417+
418+
```
419+
T frontend(172.20.0.3):39212 -> backend(172.20.0.5):80 [AP]
420+
GET /api/users HTTP/1.1.
421+
Host: backend:80.
422+
...
423+
```
424+
425+
### Filtering to a specific container's traffic
426+
427+
Container resolution annotates the display, but filtering still uses the
428+
underlying IP. To watch traffic for a specific container, find its IP and
429+
use a BPF host filter:
430+
431+
```
432+
% docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' auth_service
433+
172.20.0.4
434+
435+
% ngrep -r -d br-a1b2c3 -q '' host 172.20.0.4
436+
T auth_service(172.20.0.4):8080 -> redis(172.20.0.6):6379 [AP]
437+
...
438+
T redis(172.20.0.6):6379 -> auth_service(172.20.0.4):8080 [AP]
439+
...
440+
```
441+
442+
Even though the BPF filter uses the raw IP, the output still shows you
443+
container names on both sides of the conversation.
444+
445+
### Monitoring DNS resolution between containers
446+
447+
* `ngrep -r -d docker0 -q '' port 53`
448+
449+
This is especially useful for catching misconfigured service discovery --
450+
you'll see which container is looking up which hostname, and what the
451+
embedded DNS server responds with:
452+
453+
```
454+
U frontend(172.18.0.3):42371 -> 127.0.0.11:53
455+
.............backend.mystack_default.....
456+
U 127.0.0.11:53 -> frontend(172.18.0.3):42371
457+
.............backend.mystack_default..............172.18.0.5...
458+
```

config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
/* routine used for restarting the BPF lexer */
6464
#undef PCAP_RESTART_FUNC
6565

66+
/* whether to enable container name resolution (default off) */
67+
#undef USE_CONTAINER_RESOLUTION
68+
6669
/* whether to use privileges dropping (default yes) */
6770
#undef USE_DROPPRIVS
6871

configure

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ enable_pcap_restart
696696
enable_pcre2
697697
enable_tcpkill
698698
enable_vlan_hack
699+
enable_container_resolution
699700
with_pcap_includes
700701
with_pcre2_includes
701702
'
@@ -1346,6 +1347,9 @@ Optional Features:
13461347
--disable-vlan-hack disable automatic inclusion of VLAN frames (default
13471348
on)
13481349
1350+
--disable-container-resolution
1351+
disable container name resolution (default on)
1352+
13491353
Optional Packages:
13501354
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
13511355
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
@@ -4041,6 +4045,32 @@ esac
40414045
fi
40424046

40434047

4048+
# Check whether --enable-container-resolution was given.
4049+
if test ${enable_container_resolution+y}
4050+
then :
4051+
enableval=$enable_container_resolution;
4052+
use_container_resolution="$enableval"
4053+
4054+
else case e in #(
4055+
e) use_container_resolution="yes" ;;
4056+
esac
4057+
fi
4058+
4059+
4060+
if test $use_container_resolution = yes
4061+
then :
4062+
4063+
USE_CONTAINER_RESOLUTION="1"
4064+
EXTRA_OBJS="$EXTRA_OBJS container-resolution.o"
4065+
4066+
else case e in #(
4067+
e)
4068+
USE_CONTAINER_RESOLUTION="0"
4069+
;;
4070+
esac
4071+
fi
4072+
4073+
40444074

40454075
# Check whether --with-pcap-includes was given.
40464076
if test ${with_pcap_includes+y}
@@ -5360,6 +5390,9 @@ printf "%s\n" "#define USE_TCPKILL $USE_TCPKILL" >>confdefs.h
53605390
printf "%s\n" "#define USE_VLAN_HACK $USE_VLAN_HACK" >>confdefs.h
53615391

53625392

5393+
printf "%s\n" "#define USE_CONTAINER_RESOLUTION $USE_CONTAINER_RESOLUTION" >>confdefs.h
5394+
5395+
53635396

53645397
printf "%s\n" "#define USE_DROPPRIVS $USE_DROPPRIVS" >>confdefs.h
53655398

@@ -5478,6 +5511,20 @@ printf "%s\n" "CONFIG: NOT automatically including VLAN frames" >&6; }
54785511
esac
54795512
fi
54805513

5514+
if test "$USE_CONTAINER_RESOLUTION" = "1"
5515+
then :
5516+
5517+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: CONFIG: container name resolution enabled" >&5
5518+
printf "%s\n" "CONFIG: container name resolution enabled" >&6; }
5519+
5520+
else case e in #(
5521+
e)
5522+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: CONFIG: container name resolution disabled" >&5
5523+
printf "%s\n" "CONFIG: container name resolution disabled" >&6; }
5524+
;;
5525+
esac
5526+
fi
5527+
54815528

54825529
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
54835530
printf "%s\n" "" >&6; }

configure.ac

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ AS_IF([test $use_vlan_hack = yes], [
199199
USE_VLAN_HACK="0"
200200
])
201201

202+
dnl
203+
dnl Container name resolution support
204+
dnl
205+
206+
AC_ARG_ENABLE([container-resolution], [
207+
AS_HELP_STRING([--disable-container-resolution], [disable container name resolution (default on)])],
208+
[
209+
use_container_resolution="$enableval"
210+
],
211+
[ use_container_resolution="yes" ])
212+
213+
AS_IF([test $use_container_resolution = yes], [
214+
USE_CONTAINER_RESOLUTION="1"
215+
EXTRA_OBJS="$EXTRA_OBJS container-resolution.o"
216+
], [
217+
USE_CONTAINER_RESOLUTION="0"
218+
])
219+
202220

203221
AC_ARG_WITH([pcap-includes], [
204222
AS_HELP_STRING([--with-pcap-includes=dir], [specify the pcap include directory])],
@@ -553,6 +571,7 @@ AC_DEFINE_UNQUOTED(USE_PCRE2, $USE_PCRE2, [wheth
553571
AC_DEFINE_UNQUOTED(USE_IPv6, $USE_IPv6, [whether to use IPv6 (default off)])
554572
AC_DEFINE_UNQUOTED(USE_TCPKILL, $USE_TCPKILL, [whether to enable tcpkill functionality (default off)])
555573
AC_DEFINE_UNQUOTED(USE_VLAN_HACK, $USE_VLAN_HACK, [whether to automatically include VLAN frames (default on)])
574+
AC_DEFINE_UNQUOTED(USE_CONTAINER_RESOLUTION, $USE_CONTAINER_RESOLUTION, [whether to enable container name resolution (default off)])
556575

557576
AC_DEFINE_UNQUOTED(USE_DROPPRIVS, $USE_DROPPRIVS, [whether to use privileges dropping (default yes)])
558577
AC_DEFINE_UNQUOTED(DROPPRIVS_USER, "$DROPPRIVS_USER", [pseudo-user for running ngrep (default "nobody")])
@@ -615,6 +634,12 @@ AS_IF([test "$USE_VLAN_HACK" = "1"], [
615634
AC_MSG_RESULT(CONFIG: NOT automatically including VLAN frames)
616635
])
617636

637+
AS_IF([test "$USE_CONTAINER_RESOLUTION" = "1"], [
638+
AC_MSG_RESULT(CONFIG: container name resolution enabled)
639+
], [
640+
AC_MSG_RESULT(CONFIG: container name resolution disabled)
641+
])
642+
618643
dnl
619644
dnl And we're done. ALL YOUR BASE. Don't forget.
620645
dnl

0 commit comments

Comments
 (0)