Skip to content
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

systemd: Replace User=nobody with DynamicUser=yes #2161

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Frederick888
Copy link

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

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
@Frederick888 Frederick888 marked this pull request as ready for review November 19, 2022 15:52
@AkinoKaede
Copy link
Contributor

AkinoKaede commented Nov 19, 2022

#428

Before we change it, we must notify packagers of Linux distributions.

@AkinoKaede AkinoKaede added the Extensive Review Required Require an extensive review from organization owner, cannot be merged without owner approval label Nov 29, 2022
@github-actions
Copy link
Contributor

It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

@mydogshitgold
Copy link
Contributor

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.

@AkinoKaede
Copy link
Contributor

AkinoKaede commented Jul 29, 2023

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?

@AkinoKaede
Copy link
Contributor

cc. @IceCodeNew

Copy link
Contributor

@IceCodeNew IceCodeNew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When was this option introduced into the systemd?
Did you tested it with distros like Debian 10 (August 1st, 2022) to see if there is any problem?

Copy link
Contributor

@IceCodeNew IceCodeNew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moreover ProtectSystem=strict and ProtectHome=read-only are implied, thus prohibiting the service to write to arbitrary file system locations. In order to allow the service to write to certain directories, they have to be allow-listed using ReadWritePaths=, but care must be taken so that UID/GID recycling doesn't create security issues involving files created by the service. Use RuntimeDirectory= (see below) in order to assign a writable runtime directory to a service, owned by the dynamic user/group and removed automatically when the unit is terminated. Use StateDirectory=, CacheDirectory= and LogsDirectory= in order to assign a set of writable directories for specific purposes to the service in a way that they are protected from vulnerabilities due to UID reuse (see below).

  1. Are you sure we do not need to ship the security enforcement along with decent default values of these options?
  2. I do not expect average users to have ideas of avoiding the problem of UID reuse, not even to be aware of them. It looks like we are introducing another problem to solve an existing one. Does it ever concern you?

@IceCodeNew
Copy link
Contributor

just a kindly ping
@Frederick888 @AkinoKaede

Copy link
Contributor

It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

@github-actions github-actions bot added the Stale label Mar 26, 2024
@IceCodeNew
Copy link
Contributor

ping @Frederick888 @AkinoKaede

@IceCodeNew
Copy link
Contributor

IceCodeNew commented Mar 26, 2024

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.

@felixonmars
Copy link
Contributor

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).

@IceCodeNew
Copy link
Contributor

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

@YHNdnzj
Copy link

YHNdnzj commented Mar 26, 2024

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

@YHNdnzj
Copy link

YHNdnzj commented Mar 26, 2024

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.

@IceCodeNew
Copy link
Contributor

IceCodeNew commented Mar 26, 2024

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)
image

VS

https://docs.docker.com/compose/compose-file/05-services/
(84 options with a roughly count)
image

@IceCodeNew
Copy link
Contributor

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/

@YHNdnzj
Copy link

YHNdnzj commented Mar 26, 2024

# 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...

@github-actions github-actions bot removed the Stale label Mar 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Extensive Review Required Require an extensive review from organization owner, cannot be merged without owner approval
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants