Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,95 @@ hexadecimal form.
As it turns out, several other packets also matched this pattern, but this
should give you a good idea of how to use hexadecimal patterns and the hex
output mode.

## Container name resolution (Docker / Podman)

When running ngrep on a host that has Docker or Podman containers, raw IP
addresses on a bridge network are essentially meaningless -- they're ephemeral
and change on every `docker-compose up`. Pass `-r` to resolve container IPs to
their names, making the output immediately readable.

Container resolution is compiled in by default (disable at build time with
`--disable-container-resolution` if needed).

If the Docker (or Podman) socket is accessible, ngrep uses the Events API for
real-time tracking -- new containers show up the instant they start, and dead
ones are purged immediately. If the socket isn't available (e.g. rootless
Podman, permission issues), it falls back to CLI-based polling with a
30-second cache TTL.

### Debugging microservice traffic

Suppose you have a typical compose stack -- an API gateway, an auth service,
and a Postgres database. Without container resolution, you'd see something
like:

```
# ngrep -d docker0 -W byline port 5432
T 172.18.0.4:48120 -> 172.18.0.2:5432 [AP]
...
T 172.18.0.2:5432 -> 172.18.0.4:48120 [AP]
...
```

With `-r`, the same capture becomes:

```
# ngrep -r -d docker0 -W byline port 5432
container: using docker socket for real-time events
T api_gateway(172.18.0.4):48120 -> postgres_db(172.18.0.2):5432 [AP]
...
T postgres_db(172.18.0.2):5432 -> api_gateway(172.18.0.4):48120 [AP]
...
```

No more cross-referencing `docker inspect` output.

### Watching HTTP traffic across a compose stack

* `ngrep -r -d br-a1b2c3 -W byline -q 'GET|POST' port 80`

Monitor all HTTP traffic on a Docker Compose bridge network. Each request
shows which container is talking to which, e.g.:

```
T frontend(172.20.0.3):39212 -> backend(172.20.0.5):80 [AP]
GET /api/users HTTP/1.1.
Host: backend:80.
...
```

### Filtering to a specific container's traffic

Container resolution annotates the display, but filtering still uses the
underlying IP. To watch traffic for a specific container, find its IP and
use a BPF host filter:

```
% docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' auth_service
172.20.0.4

% ngrep -r -d br-a1b2c3 -q '' host 172.20.0.4
T auth_service(172.20.0.4):8080 -> redis(172.20.0.6):6379 [AP]
...
T redis(172.20.0.6):6379 -> auth_service(172.20.0.4):8080 [AP]
...
```

Even though the BPF filter uses the raw IP, the output still shows you
container names on both sides of the conversation.

### Monitoring DNS resolution between containers

* `ngrep -r -d docker0 -q '' port 53`

This is especially useful for catching misconfigured service discovery --
you'll see which container is looking up which hostname, and what the
embedded DNS server responds with:

```
U frontend(172.18.0.3):42371 -> 127.0.0.11:53
.............backend.mystack_default.....
U 127.0.0.11:53 -> frontend(172.18.0.3):42371
.............backend.mystack_default..............172.18.0.5...
```
3 changes: 3 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
/* routine used for restarting the BPF lexer */
#undef PCAP_RESTART_FUNC

/* whether to enable container name resolution (default off) */
#undef USE_CONTAINER_RESOLUTION

/* whether to use privileges dropping (default yes) */
#undef USE_DROPPRIVS

Expand Down
47 changes: 47 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ enable_pcap_restart
enable_pcre2
enable_tcpkill
enable_vlan_hack
enable_container_resolution
with_pcap_includes
with_pcre2_includes
'
Expand Down Expand Up @@ -1346,6 +1347,9 @@ Optional Features:
--disable-vlan-hack disable automatic inclusion of VLAN frames (default
on)

--disable-container-resolution
disable container name resolution (default on)

Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
Expand Down Expand Up @@ -4041,6 +4045,32 @@ esac
fi


# Check whether --enable-container-resolution was given.
if test ${enable_container_resolution+y}
then :
enableval=$enable_container_resolution;
use_container_resolution="$enableval"

else case e in #(
e) use_container_resolution="yes" ;;
esac
fi


if test $use_container_resolution = yes
then :

USE_CONTAINER_RESOLUTION="1"
EXTRA_OBJS="$EXTRA_OBJS container-resolution.o"

else case e in #(
e)
USE_CONTAINER_RESOLUTION="0"
;;
esac
fi



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


printf "%s\n" "#define USE_CONTAINER_RESOLUTION $USE_CONTAINER_RESOLUTION" >>confdefs.h



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

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

if test "$USE_CONTAINER_RESOLUTION" = "1"
then :

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: CONFIG: container name resolution enabled" >&5
printf "%s\n" "CONFIG: container name resolution enabled" >&6; }

else case e in #(
e)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: CONFIG: container name resolution disabled" >&5
printf "%s\n" "CONFIG: container name resolution disabled" >&6; }
;;
esac
fi


{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
printf "%s\n" "" >&6; }
Expand Down
25 changes: 25 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,24 @@ AS_IF([test $use_vlan_hack = yes], [
USE_VLAN_HACK="0"
])

dnl
dnl Container name resolution support
dnl

AC_ARG_ENABLE([container-resolution], [
AS_HELP_STRING([--disable-container-resolution], [disable container name resolution (default on)])],
[
use_container_resolution="$enableval"
],
[ use_container_resolution="yes" ])

AS_IF([test $use_container_resolution = yes], [
USE_CONTAINER_RESOLUTION="1"
EXTRA_OBJS="$EXTRA_OBJS container-resolution.o"
], [
USE_CONTAINER_RESOLUTION="0"
])


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

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

AS_IF([test "$USE_CONTAINER_RESOLUTION" = "1"], [
AC_MSG_RESULT(CONFIG: container name resolution enabled)
], [
AC_MSG_RESULT(CONFIG: container name resolution disabled)
])

dnl
dnl And we're done. ALL YOUR BASE. Don't forget.
dnl
Expand Down
Loading