Home Assistant Community Add-on: WireGuard

I might be missing this, but is there instructions on how to set this up as a client? I would have Wireguard server on my UniFi UDM SE at home, and looking to have a Wireguard VPN connector to a Home Assisstant installation running on a VM at a vacation home so I can connect the two instances with ‘Remote Home Assistant’ or have easy access.

1 Like

Hi,

I’ve got running Wiregurd add-on fine. I can access local lan and browse the internet with my home ip when I’m abroad with ad blocking using the Adguard add on. All ok so far, but now I also got a dual stack fiber connection from KPN in the Netherlands. But when I am abroad on a different dual stack network, I only get an ipv4 connection. So I searched and tried to play with the configs.
I added my local adguard dns ipv6 address to the config and gave my clients an ipv6 address as well.

When I save the config and the add on restarts I see in the logs that the wg0 interface gets deleted:

Error: IPv6 is disabled on nexthop device.

[#] resolvconf -d wg0 -f

mv: can’t rename ‘/etc/resolv.conf.913.openresolv’: Resource busy

[#] ip link delete dev wg0

Is this an error or missing config in Docker? I run HA as a vm in Esxi.
Hope anybody has a clue.

Thanks and regards,

Renzo

The instruction video is no longer available -

Can’t find the folder where the QR codes are stored. My HA is hosted supervised on Debian. Anyone has a clue? I tried to search here but no luck.

Edit: Nevermind. The configurations are in /usr/share/hassio/ssl/wireguard

I want to use wireguard on hassos (raspberry pi).

My configuration:

  • static internal ip on hassos (192.168.0.69, my internal net is 192.168.0.0/24)
  • public ip on my router
  • port forward (51820 udp) to my hassos pi
  • wireguard net 192.168.1.0/24

No addons like dns, adguard only dhcp addon is used to assign ip addresses.

My wireguard config:

host: XX.152.155.70
addresses:
  - 192.168.1.1
dns:
  - 8.8.8.8
  - 8.8.4.4

client:

- name: christopher-phone
  addresses:
    - 192.168.1.2
  allowed_ips: []
  client_allowed_ips: []

I can connect to wireguard on hassos, my phone or laptop shows active.

But i’m not able to connect to any ressource on internal lan.

What’s the problem here?

→ after a reboot of hassos and phone it now works like expected. no error in configuration. thx

This post details the setup of a point-to-point Wireguard tunnel where a NAT local to Wireguard service running in the Wireguard Add-On allows external access to ssh and the web interface from the remote network.

This avoids sharing the entire HA Network which could lead to trouble if you have more than one Home Assistant setup connecting to the remote server as the network ranges to pass through would be similar/the same. Also this avoids exposing more than is needed from the Home Assistant setup and IMHO also simplifies the HA setup as the list of allowed ips is simplified.

This setup is not meant to use your HA server as a VPN server for clients, it does not provide access to your home network through the wireguards service neither. Its only goal is to provide access to the web interface(s) and SSH service.

I am not able to control the internet box through which home assistant connects to the internet, so I have HA connect to a remote wireguard server where I also have a ha-proxy that will provide https access.

So this setup works as follows.
There is a point-to-point wireguard connection, and access to the Web UI and SSH is provided through NAT on the home assistant instance.

  • Internet → Remote server [ha-proxy, ssh proxyjump] → Remote WG → HA WG / NAT → [HA Web interface, SSH].

HA Wireguard configuration:

server:
  host: redacted_local
  addresses:
    - 172.16.0.2
  dns:
    - 80.80.80.80
    - 80.80.81.81
  pre_up: /ssl/pre-up.sh
  pre_down: /ssl/pre-down.sh
peers:
  - name: redacted_remote
    public_key: redacted_public key
    addresses:
      - 172.16.0.1
    allowed_ips:
      - 172.16.0.1
    client_allowed_ips: []
    endpoint: RemoteServer:51825

I added the pre-up.sh and pre-down.sh scripts in the ‘/ssl’ folder as this is the only folder that is mounted in the wireguard instance.
The setup has to use scripts as ssh_ip=${ssh_ip##* } was cut off at the space when providing the individual commands in the yaml configuration.

The scripts get the ips of the containers using nslookup on the slug .
host was not available, so I resorted to nslookup

pre-up.sh:

#!/bin/bash -xv
ssh_ip=$(nslookup a0d7b954-ssh | grep Address | tail -1)
ssh_ip=${ssh_ip##* }
ha_ip=$(nslookup home-assistant.local.hass.io | grep Address | tail -1)
ha_ip=${ha_ip##* }

# sysctl -w net.ipv4.ip_forward=1;

# my_ip = Local Wireguard IP
my_ip=172.16.0.2
iptables -t nat -A PREROUTING -d $my_ip -p tcp --dport 22 -j DNAT --to-destination $ssh_ip
iptables -t nat -A PREROUTING -d $my_ip -p tcp --dport 8123 -j DNAT --to-destination $ha_ip

pre-down.sh is essentially the same as the pre-up.sh script - -A is replaced with -D.

#!/bin/bash -xv
ssh_ip=$(nslookup a0d7b954-ssh | grep Address | tail -1)
ssh_ip=${ssh_ip##* }
ha_ip=$(nslookup home-assistant.local.hass.io | grep Address | tail -1)
ha_ip=${ha_ip##* }
my_ip=172.16.0.2

iptables -t nat -D PREROUTING -d $my_ip -p tcp --dport 22 -j DNAT --to-destination $ssh_ip
iptables -t nat -D PREROUTING -d $my_ip -p tcp --dport 8123 -j DNAT --to-destination $ha_ip

More ports can be exposed by adding the appropriate iptables commands. For example, one could also expose the supervisor, appdaemon, etc. You may need to use extra ns_lookup to determine the IP-address of these other containers to forward the traffic to the best port/ip.

Scripts must be executable:

chmod +x /ssl/*.sh

I tested on the remote using the following on the remote server (unsuccesful prior to proper NATting):

curl http://172.16.0.2:8123
# results in HA web page
echo "HELO" | nc 172.16.0.2 22 
# results in response from SSH server:
SSH-2.0-OpenSSH_9.3
Invalid SSH identification string.

After finalising the remote setup I was able to SSH to the HA machine through the public internet address. I added some trusted proxies to configuration.yaml and restarted ha to gain access to the web interface (if not, I had an error “400: Bad Request”).

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - XXX.XXX.XXX.XXX  # Remote Public IP   
    - 192.168.0.254  # Remote Firewall IP   
    - 172.30.33.0 # "Local" proxy     

The address to add can be found in ‘/config/home-assistant.log’:

assistant.components.http.forwarded] Received X-Forwarded-For header from an untrusted proxy 172.30.33.0

Hi @le_top, thank you for the guide. Your guide is exactly what i need to achieve in my environment.
I have done everything following your guide, but no avail. I wish you can help me on this matters.

My Connection flow:

Internet → Remote server → Remote WG → HA WG / NAT → [HA Web interface]

My HA Wireguard configuration:

server:
  host: 192.168.50.15 #HA local IP
  addresses:
    - 10.10.20.2 #WG Client local IP
  dns:
    - 1.1.1.1
    - 1.0.0.1
  pre_up: /ssl/pre-up.sh
  pre_down: /ssl/pre-down.sh
peers:
  - name: WG Server Remote
    public_key: haBUZbiyQ08a666666666llWdIKplucThFZuCv+TuGw= #WG Server Remote Public Key
    addresses:
      - 10.10.20.1 #WG Server Remote local IP
    allowed_ips:
      - 10.10.20.1 #WG Server Remote local IP
    client_allowed_ips: []
    endpoint: mywgremote.net:43231 #WG Server Remote Public IP

pre-up.sh:

#!/bin/bash -xv
ssh_ip=$(nslookup a0d7b954-ssh | grep Address | tail -1)
ssh_ip=${ssh_ip##* }
ha_ip=$(nslookup home-assistant.local.hass.io | grep Address | tail -1)
ha_ip=${ha_ip##* }

# sysctl -w net.ipv4.ip_forward=1;

# my_ip = Local Wireguard IP
my_ip=10.10.20.2
iptables -t nat -A PREROUTING -d $my_ip -p tcp --dport 8123 -j DNAT --to-destination $ha_ip

pre-down.sh:

#!/bin/bash -xv
ssh_ip=$(nslookup a0d7b954-ssh | grep Address | tail -1)
ssh_ip=${ssh_ip##* }
ha_ip=$(nslookup home-assistant.local.hass.io | grep Address | tail -1)
ha_ip=${ha_ip##* }
my_ip=10.10.20.2

iptables -t nat -D PREROUTING -d $my_ip -p tcp --dport 8123 -j DNAT --to-destination $ha_ip

Scripts must be executable: - DONE

chmod +x /ssl/*.sh

Trusted proxies to configuration.yaml - DONE

http:
  ip_ban_enabled: true
  login_attempts_threshold: 7
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.0.0/24
    - 172.16.0.0/25
    - 172.30.33.0/24
    - 127.0.0.1
    - 266.22.74.13# Remote Public IP
    - 10.10.30.1 # Remote Firewall IP

Log from WG Addon:

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service base-addon-banner: starting
-----------------------------------------------------------
 Add-on: WireGuard
 Fast, modern, secure VPN tunnel
-----------------------------------------------------------
 Add-on version: 0.8.1
 You are running the latest version of this add-on.
 System: Home Assistant OS 10.5  (amd64 / generic-x86-64)
 Home Assistant Core: 2023.9.2
 Home Assistant Supervisor: 2023.09.2
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
cont-init: info: running /etc/cont-init.d/config.sh
cont-init: info: /etc/cont-init.d/config.sh exited 0
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
services-up: info: copying legacy longrun api (no readiness notification)
services-up: info: copying legacy longrun status (no readiness notification)
services-up: info: copying legacy longrun wireguard (no readiness notification)
[17:32:11] INFO: Starting WireGuard...
s6-rc: info: service legacy-services successfully started
[#] /ssl/pre-up.sh
/bin/bash: -
: invalid option
Usage:	/bin/bash [GNU long option] [option] ...
	/bin/bash [GNU long option] [option] script-file ...
GNU long options:
	--debug
	--debugger
	--dump-po-strings
	--dump-strings
	--help
	--init-file
	--login
	--noediting
	--noprofile
	--norc
	--posix
	--pretty-print
	--rcfile
	--restricted
	--verbose
	--version
Shell options:
	-ilrsD or -c command or -O shopt_option		(invocation only)
	-abefhkmnptuvxBCEHPT or -o option
Unable to access interface: No such device
[#] ip link delete dev wg0
Cannot find device "wg0"
[17:32:41] INFO: Requesting current status from WireGuard...
[17:33:12] INFO: Requesting current status from WireGuard...

Happy to see that these instructions are useful !

As far as I remember I did have #!/bin/bash -xv.
However in your case the system complains : either there is an invisible character after the hyphen - or for a mysterious reason it’s not supported.
So #!/bin/bash should work - there is just less debug output from bash (-xv shows each command executed before and after resolving variables).

Edit: your log shows Shell options: -abefhkmnptuvxBCEHPT or -o option as well which lists x and v, so it looks more like there is an invisible character in the first line or “xv” is missing (but not the -)

Hi ,

Thank you for all the work done on such a fantastic addon.

I have it almost working for my needs however:

I cannot ping the peer (my phone) that is connected to wireguard. Everything works the other way around , I can access my LAN devices from my phone with no problem. I can ping all the lan devices from my phone but not the phone from devices on my LAN.

What am I missing here ?

Does your phone configuration have its own IP covered by the ‘allowed_ips’ argument?

Hi all.

First, sorry for my bad english.
I have a problem to set up a site2site connection.
Incoming traffic is all fine. No Problems.
After 2 days of reading and trying, i can now ping devices in the second LAN from the terminal of HA.
The problem i can´t solve is, that there seems to be no routing from the hassos eth0 to the wireguard-container. If i make a traceroute from my pc to a device in the second LAN, it just go to the raspberry-pi ip.
In the configuration.yaml i put this command:

command: "host_result=$(host a0d7b954-wireguard); addon_ip=${host_result##* }; ip route replace 192.168.10.0/24 via $addon_ip src 192.168.1.114; ip route replace 192.168.2.0/24 via $addon_ip src 192.168.1.114;

local-lan is 192.168.1.0
vpn is 192.168.10.0
second lan i 192.168.2.0
hassos on rasp4 is 192.168.1.114

route says:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         wpad.fritz.box  0.0.0.0         UG    100    0        0 eth0
172.30.32.0     *               255.255.254.0   U     0      0        0 hassio
172.30.232.0    *               255.255.254.0   U     0      0        0 docker0
192.168.1.0     *               255.255.255.0   U     100    0        0 eth0
192.168.2.0     a0d7b954-wiregu 255.255.255.0   UG    0      0        0 hassio
192.168.10.0    a0d7b954-wiregu 255.255.255.0   UG    0      0        0 hassio

I think i need some routing between eth0 and the hassio device.

I hope that my englishskills are enough, that you understand what i try to say :slight_smile:

MfG Manley

Hi thank you for the reply, this is my MIkrotik router as my WG Server Remote local IP. I have try swapping with 0.0.0.0/0, but no avail.

After a few days of struggling i Opted for the easier solution which have the same result, using Tailscale more details below, credit to @lmagyar and @OH1MAC

@devilization The first issue to solve was that the script adding the NAT rule was not working because the first line of the script was not ok. You probably did not need the swapping. (Note to other readers: this was for the point-to-point configuration).

@Manley According to your message, your site to site connection is at least partly working as you want, so the Wireguard connection is established. (Note to other readers: this is for a site-to-site configuration).

You want a PC in your network to use to use this Wireguard tunnel on your Home Assistant instance.
You need two conditions:

  1. Your PC directs traffic for this IP range to Home Assistant’s IP as a gateway.
    Either HA is your PC’s gateway, or, your PC has a route defined for that. Defining routes on a PC on every reconnect is a pain in the a** so I would be tempted to have HA as the DHCP server setting HA as the gateway, or configure the current DHCP server to distribute HA as the gateway.
  2. Home Assistant needs to accept this traffic and route it through the Wireguard tunnel. If you can ping devices on the remote site from the HA ssh add-on, then I think that routing is ok in the HA setup.

IMHO a better solution would be to install Wireguard on your PC and connect your PC to the remote site using Wireguard. Your PC’s Wireguard would add the route on your PC on every connection.

If you want to have any PC using HA’s WG tunnel to connect to the remote devices, then you definitively have to define HA as the gateway.

Thanks for the quick answer.
I have some devices in my local LAN, that need to talk with the second LAN. So i need the HA as gateway. The routing to the HA-Raspberry (192.168.1.114) is static in the router-configuration. A traceroute confirm that settings.
When i make a ping from the HA ssh i think the ping starts from the hassio-device. So the communication between the containers is correct. Just when a ping comes through the eth0 und have to be route to the hassio, it fails.

Traceroute from my pc to a VPN-client in the second LAN:

Routenverfolgung zu 192.168.10.3 über maximal 30 Hops

  1    <1 ms    <1 ms    <1 ms  FRITZBOX [192.168.1.1]
  2    <1 ms    <1 ms    <1 ms  homeassistant [192.168.1.114]
  3     *        *        *     Zeitüberschreitung der Anforderung.

A traceroute vom the HA Terminal to the same VPN-client:

traceroute to 192.168.10.3 (192.168.10.3), 30 hops max, 46 byte packets
 1  a0d7b954-wireguard.local.hass.io (172.30.33.1)  0.021 ms  0.018 ms  0.016 ms
 2  192.168.10.1 (192.168.10.1)  11.917 ms  10.823 ms  10.928 ms
 3  192.168.10.3 (192.168.10.3)  61.326 ms  29.283 ms  27.473 ms

The physical network card seems to be attached to home assistant container, so IMHO you need to add the route there.

You can examine this answer to see how to do it in with as “startup” add-on.

Or you can probably run a shell_command in an automation after startup.

I added the following to my configuration and restart ha:

shell_command:
  my_shell_cmd: /config/my_shell_cmd.sh

I created /config/my_shell_cmd.sh and did chmod +x /config/my_shell_cmd.sh

#!/bin/bash
ip address
ip route

I ran that in Developer Tools>Services:

service: shell_command.my_shell_cmd

and I found the following in the output:

  2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
  qlen 1000
      link/ether c0:3f:d5:66:d4:2f brd ff:ff:ff:ff:ff:ff
      inet 10.33.2.12/24 brd 10.33.2.255 scope global dynamic noprefixroute enp3s0
         valid_lft 1762sec preferred_lft 1762sec
      inet6 fe80::1c34:9595:664f:485c/64 scope link noprefixroute 
         valid_lft forever preferred_lft forever


  default via 10.33.2.254 dev enp3s0  src 10.33.2.12  metric 100 
  10.33.2.0/24 dev enp3s0 scope link  src 10.33.2.12  metric 100 
  172.30.32.0/23 dev hassio scope link  src 172.30.32.1 
  172.30.232.0/23 dev docker0 scope link  src 172.30.232.1

Suggesting that using the command would allow adding routes.

So now you could try to add the route you want using a shell_command that you can edit and execute without restarting HA after it’s initial setup.

Thanks for the answer.
I don´t know why i need this command to add routes, but OK. i give it a try.
My problem is, that i don´t know how to make a route from my eth0 to the wireguard-container.

The interface of your physical network is in the home assistant container - in my case it’s enp3s0 and the ip is 10.33.2.12 .
You want “any” traffic coming in on your physical interface to be routed to the wireguard interface. So IMHO that has to be set up in the container where the physical interface is defined. The shell_command is run in the HA container.

We can see some routes for the outgoing traffic in my ip route report:

  default via 10.33.2.254 dev enp3s0  src 10.33.2.12  metric 100 

The above is the default rule on my enp3s0 interface indicating that by default traffic is sent to my network’s gateway.

  10.33.2.0/24 dev enp3s0 scope link  src 10.33.2.12  metric 100 

The above rule indicates that any local traffic (my home 10.33.2.0/24 network) does not need the gateway…

Now, you want to use your Home Assistant setup as a gateway. If you remote network knows how to send traffic back through the Wireguard tunnel, the configuration will be simple. If not you’ll need to think about NATting . That is because a simple new ip route will deliver the packet from your PC to the remote network indicating that the source is 192.168.1.100 for instance (supposing that is your PC). The device on the second network (192.168.10.3 for instance) will then reply to 192.168.1.100 according to the route it knows. If it does not have the correct route for that, then the return packet never arrives at destination.
If you would have NAT, then the device on the second network would see a packet coming from 192.168.10.1:PORT instead of 192.168.1.100, and reply to 192.168.10.1:PORT where a NAT rule would translate it to 192.168.1.100:ORGPORT. As 192.168.10.1 is on the local network of 192.168.10.3 it has the proper route to send it back to 192.168.10.1 .

I think that linux - How to route all traffic from a specific interface to a specific gateway instead of default route? - Unix & Linux Stack Exchange is a good start to read from.

Thanks for all your help.
I read it all. But everything told me, that i do the right rules. So i think i don´t understand that, because it´s not running.
I wanted to switch from FHEM to HA because it should be easier. Click and done.
But i stuck since 6 days on the basic networksettings. On FHEM i have no Docker. Everything runs after 5mins.
So, thank you, but i´m done with HA.
Bye

I’ve been reading through this post, but although I found some users having the same issues, it seems to be resolved by restarting the entire host, which i’ve done.

The issue. I installed wireguard addon, added the items to the config and added a peer and added my laptop and phone. They can create an active connection, but cannot ping any hosts on the network.

Config:

host: hostname.domain
addresses:
  - 172.27.66.1
dns:
  - 192.168.20.69

DNS is my internal dns server.

Peer config:

- name: iphone
  addresses:
    - 172.27.66.2
  allowed_ips: []
  client_allowed_ips: []
- name: laptop
  addresses:
    - 172.27.66.3
  allowed_ips: []
  client_allowed_ips: []

I can’t even ping. When doing a ipconfig /all i get a 0.0.0.0 for gateway.

I forwared the UDP port to the correct IP address, and it’s open according to various port scanners.

image

But also a ping to 8.8.8.8 results in a timeout.

The behavior is the same on my iphone as it is on my laptop. Both connect, but then the connection is gone.


Changing the host to my external IP and removing the internal DNS server works. I can’t resolve my internal hostnames, but at least it works on IP base.

I can ping 192.168.20.69, but when doing ‘nslookup - 192.168.20.69’, it times out.

Any toughts on that?

Hi @frenck.

At first, let me write thank you for your great work and useful Add-on Wireguard. I use Home Assistant mainly (10+ boxes) as docker installations where I am able to setup almost anything. But there are situations where it would be better to just use Hassio installation and add-on wireguard you made. You as a creator should be the best buddy to help me solve bellow explained situation.

  1. I use home assistant on the site where I dont have public ipv4 address, neither static nor dynamic one. My question is if this add-on will help with (works in) this situation?
  2. To deal with this scenario I need HassioPeer with Wireguard Add-on to be connected to other Wireguard peer UbuntuServer with public ipv4 address endpoint. It is working and I can ping HassioPeer from UbuntuServer and also from other peers connected to this wireguard vpn network. (allowed_ip makes the magic). My question is how may I connect to HassioPeer port 8123 in this scenario from other peers? What configuration do I need to expose HassioPeer:8123 to all peers on wireguard vpn network?
  3. I do also have reverse proxy working on the UbuntuServer peer which is able to attach publicdomain.com to the peers attached to vpn network. So my last question is how to setup HassioPeer add-on wireguard in order to exposed it through this reverse proxy.

I think the situation without public ipv4 address could be common for more home assistant users. As wireguard vpn needs at least one public ipv4 it would be helpful to expand your great work above server only situations.

Thank you.