Home Assistant Community Add-on: WireGuard

Hello everyone
I have the following problem:
I already have a working VPS with Wireguard deployed on it. I already have working configurations on different devices.
I don’t understand how to configure wireguard in HAOS so that it connects to a working VPN network.

The configuration for the VPN network is as follows:
[Interface]
PrivateKey = jghdghdhdsfsjmvnbiif1745klg67d3nvf87+=
Address = 10.10.10.23/32
DNS = 10.2.0.100

[Peer]
PublicKey = iufdcjnvcLNCFJDikjfc73jmnbkv71kgvjkjflkckj=
PresharedKey = GKDyfn6933bgvf7+ydncxuuiXUIN=
Endpoint = 86.64.85.96:59675
AllowedIPs = 0.0.0.0/0,::/0
PersistentKeepalive = 5

How can I configure wireguard in HAOS so that did it connect to an already running VPN?

You can show the final version of your Wireguard configuration in Haos

Hello @mkrasavin , sure :

server:
  host: homesrv
  addresses:
    - 192.168.4.2/24
  dns: []
  private_key: <HIDDEN>
peers:
  - name: vps
    addresses:
      - 192.168.4.1/32
    allowed_ips:
      - 192.168.4.1/32
      - 192.168.4.3/32
      - 192.168.4.4/32
      - 192.168.4.5/32
    client_allowed_ips: []
    endpoint: <HIDDEN>:51820
    persistent_keep_alive: 25
    public_key: <HIDDEN>

@doron I came back here because I start having problems and I can’t understand what is going on.

The tunnel came up, I mean I can ping :

  • from my vps the homesrv, stable (ping 192.168.1.170).
  • from my homesrv the vps (ping 192.168.4.1).
  • from my phone the home srv (192.168.1.170) and the vps (192.168.4.1)

From phone (192.168.4.3) allowed ips are : 192.168.4.1/32 (vps), 192.168.4.2/32 (homesrv), 192.168.1.0/24 (my local network at home) (endpoint set to vps ip port 51820).

If I keep tabs with ping running on my vps (to 192.168.1.170), my homesrv (to 192.168.4.1) and my phone, they run without any problem until I try to reach https://192.168.1.170:8123 from my phone (chrome or homeassistant app).

At this exact moment, ping is hanging on all 3 terminals for a while. I had to wait a couple of minute to start seeing ping again. But I’m not able to reach my HA user interface on https://192.168.1.170:8123 anymore.

Do you have any idea on what can going on ?

There’s only partial info re your new setup, so let me suggest that you roll back your setup to the point it worked (as you reported above), and analyze the difference. I can wildly guess it still has something to do with your “allowed_ips” vs “addresses” but it could be other stuff.
Roll back to a working state and then apply your changes one by one, see which one breaks it.

I did not do any changes since our last discussion on the whole configuration. Added 2 others peers but it was working for weeks for all of them.

Wireguard addon has not been updated for a while, my homesrv has rebooted, but the addon and it’s configuration is a container, everything should be ok again.

Am I missing some port forwarding or other ? (Unless both my homesrv and my phone connect to the vps, I assume I don’t have to setup anything on my home routeur). Port 51820 is open on my vps.

I’m confused. At some point in our conversation, after making some changes, you said that it works. So has it been working and suddenly stopped working? Has it ever worked fully, including UI access? Can you identify what’s happened between then and when it started to act out?

You’re right at some point I came back here to thank you for your help because everything was working, including the home assistant UI at https://192.168.1.170:8123.

Strictly nothing changed in configurations (vps, homesrv and phone)

Most interesting event : power outage at home long enough for my UPS to stop, I had to reboot my NUC with HA. I can’t be sure the tunnel stopped working this day, but it’s possible.

Is it possible that I did some extra “temporary” configuration (when I first succeed in setting up everything) in network or iptables that were reseted on reboot ?

Could it be some kind of port forwarding ?

I just remember that I had to reboot my VPS too, maybe it’s on this reboot that I lost some configuration with temporary iptables rules ?

Well, maybe :slight_smile:
If you seek assistance figuring this out, it would be good to share the current state of iptables and WG routing on the VPS.
Can you share iptables state (including NAT table), and the wg0.conf from your VPS (make sure to redact keys and non-private IP addresses).

Thanks again for your help.

My VPS :

wg config

root@ubuntu:/home/me# cat /etc/wireguard/wg0.conf 
[Interface]
PrivateKey = <hidden>
ListenPort = 51820
Address = 192.168.4.1/24

[Peer]
# homesrv
PublicKey = UkuLYOrCjs5CmNns0tt3NvOBJttdMPqKI7eC5trLOzY=
AllowedIPs = 192.168.4.2/32,192.168.1.0/24

[Peer]
# phone me
PublicKey = 0lI8kQ98J+KQm49lna5+gzA0yW//SMSRzaxr1KGlWFA=
AllowedIPs = 192.168.4.3/32

[Peer]
# laptop me
PublicKey = wXlnLUqGhTPWtTEwGOLZzUu8k/It+ttHAJFH0K1ESHM=
AllowedIPs = 192.168.4.4/32

[Peer]
# phone wife
PublicKey = lVGZRm0/Du/Qy3NGd46Qo7jCIOExJyK2nTYzLMf63Ro=
AllowedIPs = 192.168.4.5/32

[Peer]
# phone kid1
PublicKey = hwsDCt4PhSxPhQIfMWuJLjpgolhQ/yUSWxT0ooFGg2Q=
AllowedIPs = 192.168.4.6/32

Iptables

root@ubuntu:/home/me# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

ip forward enabled

root@ubuntu:/home/me#  cat /etc/sysctl.conf | grep net.ipv4
#net.ipv4.conf.default.rp_filter=1
#net.ipv4.conf.all.rp_filter=1
#net.ipv4.tcp_syncookies=1
net.ipv4.ip_forward=1
#net.ipv4.conf.all.accept_redirects = 0
# net.ipv4.conf.all.secure_redirects = 1
#net.ipv4.conf.all.send_redirects = 0
#net.ipv4.conf.all.accept_source_route = 0
#net.ipv4.conf.all.log_martians = 1

vps can ping homesrv on 192.168.4.2

root@ubuntu:/home/me# ping 192.168.4.2
PING 192.168.4.2 (192.168.4.2) 56(84) bytes of data.
64 bytes from 192.168.4.2: icmp_seq=1 ttl=64 time=83.6 ms
64 bytes from 192.168.4.2: icmp_seq=2 ttl=64 time=90.7 ms
64 bytes from 192.168.4.2: icmp_seq=3 ttl=64 time=98.1 ms
64 bytes from 192.168.4.2: icmp_seq=4 ttl=64 time=90.6 ms
64 bytes from 192.168.4.2: icmp_seq=5 ttl=64 time=87.2 ms
^C
--- 192.168.4.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 83.570/90.046/98.137/4.827 ms

and on 192.168.1.170

root@ubuntu:/home/me# ping 192.168.1.170
PING 192.168.1.170 (192.168.1.170) 56(84) bytes of data.
64 bytes from 192.168.1.170: icmp_seq=1 ttl=63 time=95.9 ms
64 bytes from 192.168.1.170: icmp_seq=2 ttl=63 time=103 ms
64 bytes from 192.168.1.170: icmp_seq=3 ttl=63 time=90.9 ms
64 bytes from 192.168.1.170: icmp_seq=4 ttl=63 time=81.7 ms
64 bytes from 192.168.1.170: icmp_seq=5 ttl=63 time=89.5 ms
^C
--- 192.168.1.170 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 81.661/92.116/102.693/6.982 ms

homesrv (NUC n100 haos) in container

# docker exec -it addon_a0d7b954_wireguard bash

wireguard config (edited via HA UI)

root@a0d7b954-wireguard:/$ cat /etc/wireguard/wg0.conf 
[Interface]
Address = 192.168.4.2/24
DNS = 172.30.32.3
PrivateKey = <hidden>
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = ypNKXpemaKkV4WgDD6y/E/QerIP0r21UR9KHvUy+SUo=
AllowedIPs = 192.168.4.1/32,192.168.4.3/32,192.168.4.4/32,192.168.4.5/32
PersistentKeepalive = 25
Endpoint = <hidden>:51820

iptables

root@a0d7b954-wireguard:/$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

homesrv can ping vps

root@a0d7b954-wireguard:/$ ping 192.168.4.1
PING 192.168.4.1 (192.168.4.1): 56 data bytes
64 bytes from 192.168.4.1: seq=0 ttl=64 time=85.825 ms
64 bytes from 192.168.4.1: seq=1 ttl=64 time=86.516 ms
64 bytes from 192.168.4.1: seq=2 ttl=64 time=87.437 ms
64 bytes from 192.168.4.1: seq=3 ttl=64 time=86.911 ms
64 bytes from 192.168.4.1: seq=4 ttl=64 time=96.737 ms
^C
--- 192.168.4.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 85.825/88.685/96.737 ms

My phone config :

My phone can ping 192.168.4.1 and 192.168.1.170 :

Let me know if you need other info, and thanks again.

Okay here are a couple of things to try. Please do them in this order.

  1. Please change the “address:” in both VPS and homesrv to use /32 and not /24 as subnet mask. Restart WG on both ends.
    (check if things improve - or, got worse…)
  2. Check the NAT iptables chain on the VPS:
    iptables -S -t nat
  3. Try, on the VPS:
    curl http://192.168.1.170:8123
    See what it gets
  1. Done : no improvement (all ping goes down when I try to reach https://192.168.1.170:8123 from phone)

NB : when everything goes down it’s blocked for several minutes, I try to restart on both end, disconnect my phone, … I have no clear idea how to make it up again, I just have to wait from 2 to 20mn and restart everything… it just wake up at some point…

  1. All pings working again, NAT iptables chain on the VPS
root@ubuntu:/home/me# iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
  1. Curl from VPS :
root@ubuntu:/home/me# curl http://192.168.1.170:8123
curl: (52) Empty reply from server

root@ubuntu:/home/me# curl https://192.168.1.170:8123
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

root@ubuntu:/home/me# curl --insecure https://192.168.1.170:8123
<!DOCTYPE html><html><head><title>Home Assistant</title>...

it’s working.

  1. Bonus test, curl from mobile

it’s working !!

Then I open chrome, go to the exact same url and everything goes down :frowning:

Chrome is in the Included App list of my wireguard client (I also tested without restricting the app list)

Is there any chance your setup includes duplicate IP addresses?
The timing thing you’re describing sounds like either an ARP timeout or a NAT timeout; add to it the “empty reply” you receive on the VPS, - could someone else be responding for 192.168.1.170?

Also, please include output of “ip r” on your VPS (sorry, trying to get clarity re what’s happening). You can also try to traceroute into 192.168.1.170 from both VPS and mobile.

EDIT: The above reference to the empty reply is probably wrong - I didn’t notice you’re using insecure HTTPS and not HTTP.

sorry, trying to get clarity re what’s happening

Don’t be sorry, you’re really helpful, I’m more sorry to not be able to solve it by myself.

ip r (AAA.BBB.CCC to hide my public ip)

root@ubuntu:/home/me# ip r
default via AAA.BBB.CCC.1 dev ens6 proto dhcp src AAA.BBB.CCC.139 metric 100 
prohibit 169.254.169.254 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.1.0/24 dev wg0 scope link 
192.168.4.2 dev wg0 scope link 
192.168.4.3 dev wg0 scope link 
192.168.4.4 dev wg0 scope link 
192.168.4.5 dev wg0 scope link 
192.168.4.6 dev wg0 scope link 
AAA.BBB.CCC.1 dev ens6 proto dhcp scope link src AAA.BBB.CCC.139 metric 100 
AAA.BBB.123.16 via AAA.BBB.CCC.1 dev ens6 proto dhcp src AAA.BBB.CCC.139 metric 100 
AAA.BBB.123.17 via AAA.BBB.CCC.1 dev ens6 proto dhcp src AAA.BBB.CCC.139 metric 100

Traceroute from VPS

traceroute 192.168.1.170
traceroute to 192.168.1.170 (192.168.1.170), 30 hops max, 60 byte packets
 1  192.168.4.2 (192.168.4.2)  69.806 ms  69.766 ms  69.743 ms
 2  192.168.1.170 (192.168.1.170)  69.727 ms  69.701 ms  69.660 ms

I think you put me on the right direction with duplicate IP.

I’m behind a CGNAT, with a Flybox 5g (5g router from Orange in France). My homesrv is not close to the router so I have a repeater RE700X (tplink) to repeat wifi in my office. This repeater has a ethernet port, so homesrv is connected to this port.

I don’t really remember why but I had serious issues with wifi 6 on my NUC, this is why it’s connected with ethernet.

Repeater has DHCP desactivated and is able to extend 2.4ghz and 5ghz network.

From my Flybox 5g I’m not able to see my homesrv in listed connected device, I can see the repeater with it’s mac and 192.168.1.41 ip. One time I saw it (its mac) with 192.168.1.170 ip. So maybe, something is messing up but can’t firgure what.

I tried to factory reset my router and repeater but without success.

It’s annoying.

I want to try to force IPs to MAC but I don’t really understand what I should see, since tplink has 2 interface (2.4ghz and 5ghz, I should see 2 different mac and 2 different IPs but I see only one), how can this device manage to have an other device connected with a different IP…

Update : it’s working again !

Maybe the factory reset on all my devices helped. Will se if it’s stable again or not.

@doron thank for your help.

Hey Guys, i want to share a wireguard Dashboard using Auto-entities, Mushroom and stack-in-card.

The Dashboard:

type: custom:auto-entities
card:
  type: entities
filter:
  include:
    - entity_id: binary_sensor.wireguard_*
      options:
        type: custom:stack-in-card
        mode: vertical
        cards:
          - type: custom:mushroom-title-card
            title: >-
              {{ state_attr('this.entity_id', 'friendly_name') |
              replace('Wireguard Client ', '') }}
          - type: custom:mushroom-template-card
            entity: this.entity_id
            icon: mdi:lock
            icon_color: |-
              {% if is_state('this.entity_id', 'on') %}
                blue
              {% else %}
               red
              {% endif %}
            primary: "Status:"
            secondary: >-
              {{ "Verbunden" if (state_attr('this.entity_id',
              'latest_handshake') > ( as_timestamp(now()) ) -120) else "Nicht
              verbunden" }}
            tap_action:
              action: more-info
            hold_action:
              action: more-info
            layout: vertical
          - type: custom:mushroom-template-card
            entity: this.entity_id
            icon: mdi:eye
            icon_color: |-
              {% if is_state('this.entity_id', 'on') %}
                blue
              {% endif %}
            primary: "Letzter Handschlag:"
            secondary: >-
              {{ state_attr('this.entity_id', 'latest_handshake') | int |
              timestamp_custom('%d.%m.%Y, %H:%M')}}
            tap_action:
              action: more-info
            hold_action:
              action: more-info
            layout: vertical
          - type: custom:mushroom-template-card
            entity: this.entity_id
            icon: mdi:upload-lock
            icon_color: |-
              {% if is_state('this.entity_id', 'on') %}
                blue
              {% endif %}
            primary: "Gesendet:"
            secondary: >-
              {{ state_attr('this.entity_id', 'transfer_tx')  | int |
              filesizeformat() }}
            tap_action:
              action: more-info
            hold_action:
              action: more-info
            layout: vertical
          - type: custom:mushroom-template-card
            entity: sensor.wireguard_vpn_clients
            icon: mdi:download-lock
            icon_color: |-
              {% if is_state('this.entity_id', 'on') %}
                blue
              {% endif %}
            primary: "Empfangen:"
            secondary: >-
              {{ state_attr('this.entity_id', 'transfer_rx') | int |
              filesizeformat() }}
            tap_action:
              action: more-info
            hold_action:
              action: more-info
            layout: vertical
sort:
  method: state
  reverse: true

Rest Sensor:

- resource: http://a0d7b954-wireguard
  sensor:
    name: Wireguard VPN Clients
    icon: mdi:vpn
    json_attributes:
      - MobilSeb
    value_template: "OK"

The template Sensor:

wireguard_client_mobil_seb:
      friendly_name: Wireguard Client Seb Mobil
      icon_template: mdi:vpn
      value_template: >-
        {% if state_attr('sensor.wireguard_vpn_clients', 'MobilSeb').latest_handshake > ( as_timestamp(now()) ) -120 %}
            on
          {% else %}
            off
          {% endif %}
      attribute_templates:
        endpoint: "{{ state_attr('sensor.wireguard_vpn_clients',
          'MobilSeb').endpoint }}"
        latest_handshake: "{{ state_attr('sensor.wireguard_vpn_clients',
          'MobilSeb').latest_handshake }}"
        transfer_tx: "{{ state_attr('sensor.wireguard_vpn_clients',
          'MobilSeb').transfer_tx }}"
        transfer_rx: "{{ state_attr('sensor.wireguard_vpn_clients',
          'MobilSeb').transfer_rx }}"

I have added wireguard to HA. Now using my phone and the QR code I can create a tunnel. But nothing on the phone can actually get to the outside world. No google, no netflix. What am I doing wrong? Thanks Ben

I found that setting the dns to my router did not work, because my router does not provide dns. So I set it to 8.8.8.8. Now it looks like it is working, but… it is not.
When I connect my mobile to the vpn, the icon (key) shows I am connected, secure. But if I google “what is my ip” on the phone, my external ip is not the ip my provider is giving me. And I expected that. It also shows the wrong the location.

So basically although the vpn is up, everything on my phone is still going through the normal channels, not via the tunnel.

So Somehow I need to configure the wiregaudr server that it oushes a “route” to the client to make sure all traffic goes through the vpn. How do I do that?

Figured it out: Allowed Ips should be 0.0.0.0/0