systemd: Replace User=nobody with DynamicUser=yes
systemd warning:
Special user nobody configured, this is not safe!
DynamicUser [1] seems to be the recommended approach now. See also [2].
[1] https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DynamicUser= [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=976858
#428
Before we change it, we must notify packagers of Linux distributions.
It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days
Processes running as nobody can ptrace each other, so there is a loss of security if more than one thing is running as that user. Ideally, individual users/DynamicUser would be used in this case.
Also, according to LSB, the user "nobody" is used by NFS as a placeholder for "unmapped" users.
It seems that only Arch-based Linux distros will be affected by this change, and considering that Arch Linux users are generally more professional, I think this change can be merged. @felixonmars, what do you think about this?
cc. @IceCodeNew
just a kindly ping @Frederick888 @AkinoKaede
It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days
ping @Frederick888 @AkinoKaede
I would suggest closing this pull request since not many users have expressed concern about this issue. On the other hand, there is a high probability that users may encounter new failures.
However, the vulnerability raised by issue #428 is valid. If fixing the problem is not the preferred approach, then it is essential to provide a clear warning to users.
In addition to emphasizing that installing V2ray with distributed packages is not secure out of the box, I believe it would be sensible to suggest that users deploy V2ray through Docker containers, which should be much more painless for further security adaptions.
Sorry for not showing up earlier. Generally, I'm in favor of these types of changes, but I never really figured out how to, for example, associate DynamicUser with a specific path configured 700 (so that it's not readable by everyone).
Sorry for not showing up earlier. Generally, I'm in favor of these types of changes, but I never really figured out how to, for example, associate DynamicUser with a specific path configured 700 (so that it's not readable by everyone).
That is exactly the case. Limiting file access within Docker containers is generally considered easier and more reliable compared to implementing similar restrictions in systemd. Additionally, Docker allows for the limitation of Linux capabilities and provides other security features.
I believe that achieving similar security constraints using a tech stack other than Docker is possible. However, when it comes to systemd, users might have to refer to lengthy documentation where the relevant options are scattered throughout, making it more challenging to configure.
By suggesting the use of Docker containers, users can benefit from a more streamlined and centralized approach to security, thereby simplifying the implementation of necessary restrictions.
Here is a deployment in real life, I wrote the configuration within about 5-10 mins. I doubt anyone can do the same in systemd while taking time no longer than 1 hour.
v2ray:
cap_drop:
- ALL
command: [ "run", "-d", "/usr/local/etc/v2ray/conf.d/" ]
container_name: <REDACTED>
image: <REDACTED>
init: true
network_mode: "service:caddy"
pull_policy: always
read_only: true
restart: always
sysctls:
# mitigate TIME-WAIT Assassination hazards in TCP
- net.ipv4.tcp_rfc1337=1
# SACK is commonly exploited and rarely used
- net.ipv4.tcp_sack=0
- net.ipv4.tcp_dsack=0
- net.ipv4.tcp_fack=0
# SSR could impact TCP's performance on a fixed-speed network (e.g., wired)
- net.ipv4.tcp_slow_start_after_idle=0
ulimits:
nproc: 16384
nofile:
soft: 16384
hard: 16384
memlock:
soft: 8192
hard: 16384
volumes:
- type: bind
source: ./v2ray/conf.d/
target: /usr/local/etc/v2ray/conf.d/
read_only: true
Limiting file access within Docker containers is generally considered easier and more reliable compared to implementing similar restrictions in systemd. Additionally, Docker allows for the limitation of Linux capabilities and provides other security features.
I believe that achieving similar security constraints using a tech stack other than Docker is possible. However, when it comes to systemd, users might have to refer to lengthy documentation where the relevant options are scattered throughout, making it more challenging to configure.
Sorry, but I think your opinion is highly biased. Just because you're more used to Docker doesn't mean that systemd is substantially harder. I wrote the following service in 3 minutes and I have been using it everyday for 2 years:
# /etc/systemd/system/[email protected]
[Unit]
Description=V2Ray instance for %i
Documentation=https://www.v2fly.org
[Service]
DynamicUser=yes
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
ConfigurationDirectory=v2ray
ConfigurationDirectoryMode=0700
LoadCredential=config:/etc/v2ray/%i.json
ExecStart=/usr/bin/v2ray run -config "${CREDENTIALS_DIRECTORY}/config" -format jsonv5
Restart=on-failure
RestartPreventExitStatus=23
ProtectSystem=strict
ProtectHome=yes
PrivateDevices=yes
PrivateUsers=yes
ProtectHostname=yes
ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
LoadCredential= only passes the selected config into service, so it's more secure than bind mounting the whole config dir. Also, this integrates better with the service manager, allowing for more precise job ordering.
Limiting file access within Docker containers is generally considered easier and more reliable compared to implementing similar restrictions in systemd. Additionally, Docker allows for the limitation of Linux capabilities and provides other security features. I believe that achieving similar security constraints using a tech stack other than Docker is possible. However, when it comes to systemd, users might have to refer to lengthy documentation where the relevant options are scattered throughout, making it more challenging to configure.
Sorry, but I think your opinion is highly biased. Just because you're more used to Docker doesn't mean that systemd is substantially harder. I wrote the following service in 3 minutes and I have been using it everyday for 2 years:
# /etc/systemd/system/[email protected] [Unit] Description=V2Ray instance for %i Documentation=https://www.v2fly.org [Service] DynamicUser=yes CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE ConfigurationDirectory=v2ray ConfigurationDirectoryMode=0700 LoadCredential=config:/etc/v2ray/%i.json ExecStart=/usr/bin/v2ray run -config "${CREDENTIALS_DIRECTORY}/config" -format jsonv5 Restart=on-failure RestartPreventExitStatus=23 ProtectSystem=strict ProtectHome=yes PrivateDevices=yes PrivateUsers=yes ProtectHostname=yes ProtectClock=yes ProtectKernelTunables=yes ProtectKernelModules=yes ProtectKernelLogs=yes ProtectControlGroups=yes LockPersonality=yes MemoryDenyWriteExecute=yes
That is cool. I am glad you find you way out and willing to share it.
For your argument, I do not think we are talking in the same language. The reason I prefer to recommend users to use docker is as following:
However, when it comes to systemd, users might have to refer to lengthy documentation where the relevant options are scattered throughout, making it more challenging to configure.
Here is a example:
read_only: true
VS
> ProtectSystem=strict
> ProtectHome=yes
> PrivateDevices=yes
> PrivateUsers=yes
# PrivateTmp= ?
# RestrictFileSystems= ?
I am confident about how proficient I am in systemd configurations, and I believe there are more options to fill the gap between the docker configurations and systemd configurations, just in terms of restricting file access. The above was what I can recall in a fraction of time. And all of those options are scattered throughout a lengthy documentation.
https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html
(189 options with a roughly count)
VS
https://docs.docker.com/compose/compose-file/05-services/
(84 options with a roughly count)
Not to mention you have missed the seccomp configuration in the systemd configuration, which comes out of the box in the docker engine ;-)
If you are interested, you may refer to: https://prefetch.net/blog/index.php/2017/11/27/securing-systemd-services-with-seccomp-profiles/
# PrivateTmp= ?
# RestrictFileSystems= ?
The former is implied by DynamicUser=yes. I don't think there's any need to use latter. The process won't have privilege to mount extra file systems anyway.
If you are interested, you may refer to: https://prefetch.net/blog/index.php/2017/11/27/securing-systemd-services-with-seccomp-profiles/
No need if you check my GitHub profile...
It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days