Setting up Wireguard on Fedora 39 Silverblue

I’d like to set up wireguard with wg-quick as a systemctl service.

I followed the instructions at Chapter 8. Setting up a WireGuard VPN Red Hat Enterprise Linux 9 | Red Hat Customer Portal (as well as those at Build a virtual private network with Wireguard - Fedora Magazine) and when I tried bringing the service up, I got

Dec 03 12:11:28 pi wg-quick[124827]: wg-quick: `/etc/wireguard/wg0.conf' does not exist
Dec 03 12:11:28 pi systemd[1]: wg-quick@wg0.service: Main process exited, code=exited, status=1/FAILURE
Dec 03 12:11:28 pi systemd[1]: wg-quick@wg0.service: Failed with result 'exit-code'.
Dec 03 12:11:28 pi systemd[1]: Failed to start wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0.
# ll /etc/wireguard/wg0.conf
-rw-r--r--. 1 root root 233 Dec  3 12:05 /etc/wireguard/wg0.conf
# ll $(which wg-quick)
-rwxr-xr-x. 3 root root 13464 Jan  1  1970 /usr/bin/wg-quick

Feels like I’m missing something obvious here…

Solution: start firewalld and bring up the wireguard interface before trying to enable the service :person_shrugging:

systemctl start firewalld
wg-quick up wg0
systemctl enable wg-quick@wg0

Unsolving: the above command completed, but the service still doesn’t start

# systemctl status wg-quick@wg0.service
× wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
     Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: failed (Result: exit-code) since Sun 2023-12-03 15:33:44 IST; 18s ago
       Docs: man:wg-quick(8)
             man:wg(8)
             https://www.wireguard.com/
             https://www.wireguard.com/quickstart/
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
             https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
    Process: 411182 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=1/FAILURE)
   Main PID: 411182 (code=exited, status=1/FAILURE)
        CPU: 21ms

Dec 03 15:33:44 pi systemd[1]: Starting wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0...
Dec 03 15:33:44 pi wg-quick[411182]: wg-quick: `/etc/wireguard/wg0.conf' does not exist
Dec 03 15:33:44 pi systemd[1]: wg-quick@wg0.service: Main process exited, code=exited, status=1/FAILURE
Dec 03 15:33:44 pi systemd[1]: wg-quick@wg0.service: Failed with result 'exit-code'.
Dec 03 15:33:44 pi systemd[1]: Failed to start wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0.

This looks like the problem, but you showed the file exists. Could you share the contents of the file?

Perhaps SELinux is in the way? What does ls -lZ /etc/wireguard/wg0.conf say? Or what does sudo ausearch -m avc report?

❯ sudo ls -lZ /etc/wireguard/wg0.conf
-rw-r--r--. 1 root root unconfined_u:object_r:etc_t:s0 499 Dec  3 15:25 /etc/wireguard/wg0.conf
❯ sudo ausearch -m avc
time->Wed Nov 29 02:00:25 2023
type=AVC msg=audit(1701216025.796:132): avc:  denied  { dac_override } for  pid=1179 comm="wg-quick" capability=1  scontext=system_u:system_r:wireguard_t:s0 tcontext=system_u:system_r:wireguard_t:s0 tclass=capability permissive=0
root@pi:/etc/wireguard# semanage fcontext -a -t wireguard_t '/etc/wireguard(/.*)?'

ValueError: Type wireguard_t is invalid, must be a file or device type

SELinux strikes again! I would recommend filing a bug with Fedora SELinux folks about this denial - Log in to Red Hat Bugzilla

On my F39 host, I only have two wireguard specific SELinux file contexts:

$ sudo semanage fcontext -l | grep wireguard
/usr/bin/wg-quick                                  regular file       system_u:object_r:wireguard_exec_t:s0 
/usr/lib/systemd/system/wg-quick@\.service         regular file       system_u:object_r:wireguard_unit_file_t:s0 

Neither seem appropriate for a config file in /etc/wireguard.

I do have a /etc/wireguard directory, though. Perhaps etc_t is a better type for /etc/wireguard/wg0.conf?

$ sudo ls -alZ /etc/wireguard/
total 12
drwx------.   2 root root system_u:object_r:etc_t:s0    6 Dec  2 11:51 .
drwxr-xr-x. 138 root root system_u:object_r:etc_t:s0 8192 Dec  2 11:53 ..

(Or not…I’m a bit out of my SELinux comfort zone)

Hmm I have etc_t on that file as well, though, right?

/usr/bin/wg-quick is just a shell script using [[ -e $CONFIG_FILE ]].

Are you tab-completing the path to wg0.conf? Is it possible that there’s something like a non-printable character hidden in there? Slipping a ZWNJ (U+200C) into the filename yields the results you’re seeing.

No Unicode tricks,I checked

Oops, I missed that.

As a workaround, you could try using audit2allow to generate a SELinux policy modification. I grabbed the denial message and used it locally:

$ cat audit.log 
type=AVC msg=audit(1701216025.796:132): avc:  denied  { dac_override } for  pid=1179 comm="wg-quick" capability=1  scontext=system_u:system_r:wireguard_t:s0 tcontext=system_u:system_r:wireguard_t:s0 tclass=capability permissive=0
$ audit2allow -i audit.log -m local > local.te
$ cat local.te 

module local 1.0;

require {
        type wireguard_t;
        class capability dac_override;
}

#============= wireguard_t ==============
allow wireguard_t self:capability dac_override;
$ checkmodule -M -m -o local.mod local.te
$ semodule_package -o local.pp -m local.mod
$ semodule -i local.pp

See the man page for audit2allow for more details.

I would strongly encourage you to file that selinux-policy issue…there could be something we are missing here.

WireGuard works fine for me using NetworkManager and systemd-networkd.

https://bugzilla.redhat.com/show_bug.cgi?id=2252895

1 Like

that’s fine but i’d like to follow the official howto

From that BZ, it looks like the permissions on /etc/wireguard were incorrect:

# ls -ld / /etc /etc/wireguard/
drwxr-xr-x. 1 root root  158 Dec  5 08:33 /
drwxr-xr-x. 1 root root 4112 Nov 29 02:00 /etc
d-w-------. 1 root root   84 Dec  5 09:18 /etc/wireguard/

The suggested workaround was to run rpm --restore wireguard-tools, but that’s not going to work on an Silverblue system:

$ sudo rpm --restore wireguard-tools
error: can't create transaction lock on /usr/share/rpm/.rpm.lock (Read-only file system)

I think it should be possible to just sudo chmod u+r /etc/wireguard and that would fix the permissions correctly. YMMV.

For Silverblue, one can check /usr/etc:

ls -ld /usr/etc/wireguard

The correct permission appears to be 0700.

I had this problem a while ago and was told that a non-functional systemd unit was acceptable, because they were other options, and supposedly using the wg-quick systemd unit was going “against best practices”, for some unexplained reason.

It turns out that i had a SELinux context issue, and running restorecon -R -v /etc/wireguard/ fixed it:

Relabeled /etc/wireguard/wg0.conf from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:etc_t:s0

I wonder if like me, you’d initially created the wireguard config file in your home directory @bennyp and then copied it into /etc/wireguard.

So, in summary:

  • chmod 0700 /etc/wireguard/
  • chown root: /etc/wireguard/
  • chmod 0600 /etc/wireguard/*
  • restorecon -R -v /etc/wireguard/

While rpm --restore wireguard-tools won’t work on an ostree-based system like Silverblue as already pointed out, I just tried running restorecon -R -v /etc/wireguard/ and it works.

2 Likes

You probably could have confirmed yours was selinux related by temporarily setting selinux to permissive instead of enforcing to test and see if that allowed wireguard to function properly.
That could have been done using sudo setenforce 0 to put it into permissive mode and then use sudo setenforce 1 to restore it to enforcing mode.

I don’t recommend disabling SELinux as it has a ton a weird consequences on the system and can create more problems.

If you have permissions issues and suspect this is due to SELinux, you should be able to find entries in the audit log /var/log/audit/audit.log or in the journal.

I agree 100%
Note that I did not recommend disabling it.
I instead recommended temporarily putting it into permissive mode to see if selinux was blocking wireguard for testing purposes.

Unless I am totally misunderstanding the way selinux works, permissive mode does not disable anything. It does allow things to continue that otherwise would be blocked by selinux in enforcing mode and provides a warning in the journalctl logs. All other functions of selinux remain active including the labeling of files with selinux context, etc. When a reboot is done or when the setenforce command is used to return to enforcing mode things resume as normal.

Unfortunately, the permissive mode is a super complex mode with a lot of caveats.

I’ve written more details in Clarify position around SELinux support · Issue #439 · coreos/fedora-coreos-docs · GitHub.

The summary is that you can end up with invalid file labels in permissive mode or errors that would never happen in either disabled or enforcing mode.

It’s usually better to turn permissive mode on only for a specific domain / service and not for the entire system to avoid issues.

I have never seen any problems with using permissive mode for the entire system on a temporary basis. It would seem much more complex and possibly even beyond my expertise as an experienced user to do as you suggest here.

SELinux is complex and I only use enforcing (or occasionally permissive for testing purposes) since I have no desire to dig into how it works and manage specific items of that nature.