We run code inside an Ubuntu [5.15.76-v8+] Docker container, as part of a test system, which needs to open a socket on a specific interface (ppp0, created inside the Docker container by pppd, which is in turn connected to the device under test, also running inside the Docker container), rather than sneaking it out through eth0.
When this Docker container is run under Raspbian [5.15.76-v8+], setsockopt() does this and all is fine:
struct ifreq interface = {0};
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
snprintf(interface.ifr_name, sizeof(interface.ifr_name), "ppp0");
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
&interface, sizeof(interface)) == 0) {
// Things routed through sock() appear on ppp0
...
However, when running the same Docker container in the same way (this is all done under Jenkins) on Centos8 [4.18.0-408.el8.x86_64], setsockopt() returns -1 and errno is EPERM.
I understand that setsockopt() requires CAP_NET_RAW permissions: can anyone advise why the socket permissions might be different when the Docker container is run on Centos8 and how I can make the Centos8 case work in the same way as the Raspbian case?
In case it is useful, the part of Dockerfile relevant to pppd is this:
RUN chown root /usr/sbin/pppd && chmod 4755 /usr/sbin/pppd && \
sed 's/^auth/noauth/' /etc/ppp/options > options && \
cp options /etc/ppp/options && \
rm options
[since this is an internal test system talking to a bit-pipe-under-test rather than a server we have no worries about security] and docker is run with parameters -i -u username --rm --privileged.