-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switch from tcpdump to ~~ss~~ nstat for connection checks #417
Conversation
Also, a side note, it's possible that implementations differ based on kernel or something other than what I can think of, but I see UDP connections falling off of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, thank you! 🚢
The CI check failed with the following errors:
Essentially it would like to see
|
Fixed. I should have run shellcheck. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still complaining about
#37 2.621 In /usr/local/etc/valheim/common line 143:
#37 2.621 if [ $(ss -u | grep -cF "$SERVER_PORT") -gt 0 ]; then
#37 2.621 ^-- SC2046: Quote this to prevent word splitting.
The $()
must be quoted. See my original comment above.
I tested this and it doesn't seem to work for me 🤔. Server is permanently idle according to my debug logging ( Any ideas? |
I'm unsure how it behaves in Docker with the default bridge networking there. As I mentioned, I'm running with rootless podman which means using slirp4netns networking. This is what I see:
(eta: I don't have a host with a normal docker-ce or moby installation handy to check - though I'm interested to hear if other people see the same behavior) edit2: Also, to make sure that an unprivileged user inside the container could pull the UDP socket information, I manually added a non-root user inside the container and ran this:
And that behavior is despite the fact that, in my implementation, I haven't changed the PUID for |
I'm using docker-ce as distributed with Debian 11 with default bridge networking as you mentioned. I've tried all constellations of non-root and root-users with It's interesting that both the local address and the peer address are the same for you. I guess it has something to do with how the podman networking works. |
UDP is stateless. I think that is the reason, why we don't get any information out of |
UDP is stateless, but the implementation of tracking that I'm seeing in SS is unrelated to the state of the UDP connection in the same way that the TCP session would be tracked. I noted that the connections dropped off of my I just double-checked and see that when I run Could you check the value on your host system, @Tremolo4 ? |
I also get I've tested
While on the server I can sometimes see the Recv-Q and Send-Q values going up. Note that I can also see the Valheim sockets there.
In the docker container they also show up, like this (regardless of whether someone was on the server in the last 30 seconds):
@solacelost My guess is the way your container networking works causes |
Alright - I think I have an alternative that should work. @Tremolo4 mind testing this one out before I make another commit (which I will definitely run shellcheck on 😇)? Make sure you have RUNTIME=docker # here I was using podman
UID=1000 # this should work set to any arbitrary UID, even if the user doesn't exist
CONTAINER_INSTANCE_ID=valheim # this should be the name or container ID of your Valheim container
# This should print the number of UDP datagrams received by the network namespace since it was last checked
datagrams() {
$RUNTIME exec --user $UID $CONTAINER_INSTANCE_ID nstat | \
awk '/^UdpInDatagrams/{print $2}' | \
tr -d ' '
}
datagrams_print() {
dg_count=$(datagrams)
echo ${dg_count:-0} datagrams received
}
# This is to print the timestamp to the nearest centisecond to make it easy to see the passage of time
ts() {
date +%s.%N | head -c 13
echo
}
# This throws away the starting statistics
datagrams &>/dev/null
# This is enough for you to see some traffic with a little bit of arbitrary spacing in between
ts
datagrams_print
ts
datagrams_print
sleep 0.5
ts
datagrams_print
ts This mock-up is designed to be run from your host and should demonstrate that this method will work for you on Docker on Debian with bridge networking and normal rootful docker with an unprivileged user in the container, while also working for me on Podman on Fedora with slirp4netns networking and rootless podman and either rootless or root users inside the container (because for me the majority of the caps are taken away at the runtime level). Here's my output from the above when nobody is connected to a server:
and with two users connected:
If I'm right, and this works for you, I'll have the PR patched up to measure the amount of datagrams received over a three-second period and have Edited to add one important fact: I'm running two copies of this image right now. The above |
That seems to work for me too, thanks a lot! I've confirmed that it does not pick up any other UDP traffic outside of the valheim container, not even from another valheim container. One problem is that this method can't distinguish port numbers, so we can't check for game traffic on port 2456 only. I've been running the server in public mode to make the idle check work, so I very regularly get queries on port 2457 from people refreshing the server list. They get picked up by The other non-player UDP packets I see in tcpdump are DNS queries from Since even a single player on the server causes a lot more packets per second than this, I suggest we use a threshold to determine whether it's player traffic or not. Something like 30 packets per 3 seconds should be good. With just me on the server I'm getting around 100 - 400 packets per 3 seconds, depending on whether I move around or not etc. (using Unless of course you know a way to check only a specific UDP port :D |
I can't think of a way to get per-socket statistics without enabling conntrack on the host, which goes pretty well outside of the bounds of what we should be requiring with a container. @lloesche how do you feel about the use of 30 UDP datagrams within a 3-second period being the default threshhold to identify an actively connected player, with an environment variable defined to tune it per-instance if necessary? I'll do up this implementation now and you can review shortly. |
😇 |
Just made one other tweak because my |
Annnd a rebase! Apologies for the GHA spam - I did not expect it to be quite so bad as it is. I'm not used to GHA when I'm not the approver. |
@solacelost thank you, looks good! But please restore the trailing double spaces in the README. They are Markdown syntax to enforce linefeeds. |
Any update? I'm already running this version here successfully. Just hope the PRs can get cleaned up here so I can shift back to your image :) |
This changes from tcpdumping with a 3 second timeout while looking for packets to checking
active UDP sessions being trackedincoming UDP datagrams tracked over a modifiable 3-second window, with a default idle threshold of 30 datagrams in that window.This works completely unprivileged and I can confirm it working on rootless podman with SELinux enforcing on a Fedora system. Also tested on Debian 11 with rootful podman and bridge networking by @Tremolo4 with a non-root PUID.
fixes #413