diff --git a/src/common.c b/src/common.c
index e7d49c3..95a663b 100644
--- a/src/common.c
+++ b/src/common.c
@@ -51,6 +51,11 @@
 # include <selinux/selinux.h>
 #endif
 
+#ifdef HAVE_LIBCAPNG
+#include <stdbool.h>
+#include <cap-ng.h>
+#endif
+
 #include "common.h"
 
 /* The raw header used when not using DNS protocol */
@@ -103,12 +108,60 @@ int setgroups(int count, int *groups)
 
 #ifndef WINDOWS32
 void
-check_superuser(void)
+check_privileges(char *username, int port)
 {
+#if defined HAVE_LIBCAPNG
+	bool capable = true;
+
+	if (capng_get_caps_process() == -1) {
+		warnx("Unable to get capabilities");
+		exit(-1);
+	}
+
+	if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_ADMIN)) {
+		warnx("capabilities: CAP_NET_ADMIN required");
+		capable = false;
+	}
+
+	if (port) {
+		unsigned short int ip_unprivileged_port_start = 1024;
+
+		FILE *file = fopen("/proc/sys/net/ipv4/ip_unprivileged_port_start", "r");
+		if (!file) {
+			warnx("sysctl: unable to get ip_unprivileged_port_start value");
+			// do not bail out here in case systemd.service has ProcSubset=pid set
+		} else {
+			fscanf(file, "%hu", &ip_unprivileged_port_start);
+			fclose(file);
+		}
+
+		if (port < ip_unprivileged_port_start &&
+			!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE)) {
+			warnx("capabilities: CAP_NET_BIND_SERVICE required");
+			capable = false;
+		}
+	}
+
+	if (username) {
+		if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_SETUID)) {
+			warnx("capabilities: CAP_SETUID required");
+			capable = false;
+		}
+		if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_SETGID)) {
+			warnx("capabilities: CAP_SETGID required");
+			capable = false;
+		}
+	}
+
+	if (!capable) {
+		exit(-1);
+	}
+#else
 	if (geteuid() != 0) {
 		warnx("Run as root and you'll be happy.");
 		exit(-1);
 	}
+#endif
 }
 #endif
 
diff --git a/src/common.h b/src/common.h
index 0f990c1..8b0a2a4 100644
--- a/src/common.h
+++ b/src/common.h
@@ -105,11 +105,11 @@ enum connection {
 };
 
 #ifdef WINDOWS32
-static inline void check_superuser(void)
+static inline void check_privileges(char *, int)
 {
 }
 #else
-void check_superuser(void);
+void check_privileges(char *, int);
 #endif
 char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len);
 int get_addr(char *, int, int, int, struct sockaddr_storage *);
diff --git a/src/iodine.c b/src/iodine.c
index fbb6481..88ebd21 100644
--- a/src/iodine.c
+++ b/src/iodine.c
@@ -279,7 +279,7 @@ int main(int argc, char **argv)
 		}
 	}
 
-	check_superuser();
+	check_privileges(username, 0);
 
 	argc -= optind;
 	argv += optind;
diff --git a/src/iodined.c b/src/iodined.c
index f2d1dc5..2e2d9be 100644
--- a/src/iodined.c
+++ b/src/iodined.c
@@ -2519,7 +2519,7 @@ main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
-	check_superuser();
+	check_privileges(username, port);
 
 	if (argc != 2)
 		usage();
diff --git a/src/osflags b/src/osflags
index 83561c5..99d8b8e 100755
--- a/src/osflags
+++ b/src/osflags
@@ -23,6 +23,7 @@ link)
 			"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS $($PKG_CONFIG --libs libselinux)";
 			"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd-daemon)";
 			"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd)";
+			"$PKG_CONFIG" --exists libcap-ng && FLAGS="$FLAGS $($PKG_CONFIG --libs libcap-ng)";
 			echo $FLAGS;
 		;;
 	esac
@@ -46,6 +47,7 @@ cflags)
 			"$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS -DHAVE_SETCON";
 			"$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS -DHAVE_SYSTEMD";
 			"$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS -DHAVE_SYSTEMD";
+			"$PKG_CONFIG" --exists libcap-ng && FLAGS="$FLAGS -DHAVE_LIBCAPNG";
 			echo $FLAGS;
 		;;
 		GNU/kFreeBSD|GNU)