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

Harden a bit the systemd unit. #10205

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

Harden a bit the systemd unit. #10205

wants to merge 1 commit into from

Conversation

jvoisin
Copy link

@jvoisin jvoisin commented Nov 15, 2020

@ilike2burnthing
Copy link
Contributor

Integration Tests Selenium LinuxAmdx64: Failed

ChromeDriver was started successfully.
  X CheckTitle [201ms]
  Error Message:
   Initialization method Jackett.IntegrationTests.DashboardTests.LoadDashboard threw exception. OpenQA.Selenium.WebDriverException: unknown error: net::ERR_CONNECTION_REFUSED
  (Session info: headless chrome=86.0.4240.183).
  Stack Trace:
      at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
   at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.Remote.RemoteWebDriver.set_Url(String value)
   at OpenQA.Selenium.Remote.RemoteNavigator.GoToUrl(String url)
   at Jackett.IntegrationTests.DashboardTests.LoadDashboard() in /home/vsts/work/1/s/src/Jackett.IntegrationTests/DashboardTests.cs:line 77

Standard Output Messages:
Connection refused Connection refused
[...]
Connection refused Connection refused
Url for test: http://localhost:9117/UI/Dashboard

@garfield69
Copy link
Contributor

Jackett on linux systems currently uses /.config/Jackett as the location for its Indexers and DataProtection folders, and its logs files.
Which conflicts with ProtectHome=yes
Before implementing this PR, the impact of these settings will need to be considered and mitigated.
Job for @ngosang and/or @ilike2burnthing

@ilike2burnthing
Copy link
Contributor

ngosang will have a much better idea than me, so I'll leave this one to them, but looking at the provided documentation, something similar (without breaking Jackett) may be possible using:

ReadWriteDirectories=
ReadOnlyDirectories= 
InaccessibleDirectories=

@ngosang
Copy link
Member

ngosang commented Nov 16, 2020

This has to be reviewed carefully. There are a lot of distributions out there with old Systemd versions. I will take this but I want to work on #9029 first.

@MichaIng
Copy link
Contributor

It would be even possible to apply

ProtectSystem=strict

which makes everything R/O, then

ReadWritePaths=-${JACKETT_DIR} -$(awk -v "user=${JACKETT_USER}" -F: '$1==user {print $6}' /etc/passwd)
  • This does not add further permissions, it just lifts the limit of ProtectSystem. I.e. if UNIX permissions do not permit the service user to access the paths, ReadWritePaths cannot change something about that.
  • I use leading - here to not fail here if those dirs do not exist. Otherwise the service fails with a highly cryptic error message. Better to have something meaningful logged if e.g. the executable itself does not exist or the config home cannot be created or such.
  • Btw, $HOME/.config/Jackett is used, not $PWD/.config/Jackett, right? Otherwise ${JACKETT_DIR} R/W access would be sufficient, of course.

@ngosang
Copy link
Member

ngosang commented Jan 7, 2023

I don't have much to say about that. I committed with the security but I'm not sure if this will cause issues for other users. We have thousands of users running Jackett in NAS, routers, SBC... If you are paranoid about security it will be better to run Jackett in a sandbox, cage or even in a root-less Docker.

Archlinux community also cares about security and they don't have those parameters => https://aur.archlinux.org/cgit/aur.git/tree/jackett.service?h=jackett

@jvoisin @MichaIng probably you know more than me about systemd. If you both agree in the solution, combine all the changes in one PR and it will be reviewed and merged. If some user complains it will be reverted until it's fixed.

Btw, $HOME/.config/Jackett is used, not $PWD/.config/Jackett, right? Otherwise ${JACKETT_DIR} R/W access would be sufficient, of course.

Yes.

@MichaIng
Copy link
Contributor

@ngosang
What systemd does with these directives is some sort of sandboxing. Probably not as much as a root-less Docker container, but it should reduce attach vectors quite a bit. We at DietPi use these hardenings for quite a while without issues:

ProtectSystem=strict
ProtectHome=true
PrivateDevices=true
PrivateTmp=true
ProtectKernelTunables=true
ProtectControlGroups=true
ReadWritePaths=-/opt/jackett

Quite similar. ProtectKernelModules and NoNewPrivileges should be safe to enable as well, based on what Jackett needs to do. We additionally set ProtectControlGroups, which I would suggest here as well. Those are all not mandatory, of course, but each of them adds a tiny bit of security, which does not hurt, just in case the Jackett binary is corrupted harmlessly and/or running user unexpectedly has more privileges than required/intended, like pi on Raspberry Pi which is quite mighty by default.

Not everyone who cares about security knows or has sufficient experience with those systemd hardenings, so I wouldn't take it as argument against it that the specific Arch AUR package maintainer(s) do(es) not implement them. In case of Jackett it is quite simple since it doesn't require write access to anywhere aside of its install and data dir (right?). The only issue we faced with ProtectSystem=strict or ProtectHome=true was with software which writes to customisable dirs (like Sonarr to media dirs) which users might have in a home directory or elsewhere, without adding it to ReadWritePaths.

Btw. on systemd unknown directives are just ignored with a warning in logs, so older systemd versions which do not support those (or all of them) yet will just continue to work as before.

ProtectDevices=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes

Copy link
Contributor

Choose a reason for hiding this comment

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

@ilike2burnthing
Copy link
Contributor

The only issue we faced with ProtectSystem=strict or ProtectHome=true was with software which writes to customisable dirs (like Sonarr to media dirs) which users might have in a home directory or elsewhere, without adding it to ReadWritePaths.

Jackett's user-customisable Blackhole directory: setting for torrent downloads comes to mind here. How would that be handled?

@MichaIng
Copy link
Contributor

Ah, I didn't know about that. Jackett downloads and stores magnet files into this dir, i.e. requires write access, right? In this case, for the official systemd unit, it is then better to stay with ProtectSystem=full and skip ReadWritePaths, as it is nasty for users when facing write permission issues and not knowing that systemd is blocking it (while the running user has full write access UNIX permission wise). We didn't face someone reporting such issue on DietPi yet, but I'll keep it in mind to do the same change, as fast as someone does.

@ilike2burnthing
Copy link
Contributor

ilike2burnthing commented Jan 10, 2023

I would guess most users don't use it, but for those who do, torrents are downloaded to wherever they set it (e.g. their client's watch directory).

MichaIng added a commit to MichaIng/DietPi that referenced this pull request Jan 10, 2023
- DietPi-Software | Jackett: Add some additional systemd service hardening: Jackett/Jackett#10205
- RC up
@ragnarokme
Copy link

hello everyone, I did the installation, but something went wrong, I want to completely clean the system from jackett and try again, I use ubuntu tell me the command how to do it

@davispuh
Copy link

I'm using this and it works fine

[Service]
UMask=0077
CapabilityBoundingSet=
LockPersonality=true
NoNewPrivileges=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
PrivateUsers=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=strict
ReadWritePaths=/var/lib/jackett
RemoveIPC=true
RestrictAddressFamilies=AF_INET AF_INET6
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service mincore
SystemCallFilter=~@privileged

It's pretty much all hardening you can do. Can't use MemoryDenyWriteExecute=true because .NET uses it.

$ systemd-analyze security jackett
→ Overall exposure level for jackett.service: 1.2 OK 🙂

Note I have my Blackhole directory under /var/lib/jackett that's why it works. For those who want system-wide writing they can't enable some of these options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants