Open freifunkkt opened 6 years ago
Something like this could do the trick I guess, but I haven't tested it, so it might fail horribly.
#!/bin/bash -e
BOARD=e50
if [ ! $(dpkg-query --show wireguard) ]; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
fi
Hi Lochnair,
the question was not so much which script to use. But more about if it could be included into the installer.
I will test it anyways and let you know.
Kind regards, Andreas
Hi Lochnair,
I tested the night trough different scenarios.
Generally: Partly Success, the script re-installs wireguard.
But there is certain precaution one must take:
So there is something missing that saves and reapplies everything.
Kind regards, Andreas
Eh, I wanted to write a reinstall script that works first. No point in trying to include a script that doesn't exist yet :stuck_out_tongue:. That said, I'm not sure how I feel about autoinstalling a script into post-config.d without user consent.
Thanks for testing. I had a feeling this might be the case. The WireGuard configuration is still in config.boot, but we need to load it again and commit after reinstalling WireGuard.
#!/bin/bash -e
BOARD=e50
if [ ! $(dpkg-query --show wireguard) ]; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
source /opt/vyatta/etc/functions/script-template
configure
load
commit
exit
fi
Destroys the dashboard? As in the web GUI dashboard? I've no idea what that could be, but retesting without the script would be helpful.
Hi Lochnair,
I did some more testing... You tried to run /opt/vyatta/etc/functions/script-template. But that somehow doesnt work out. I think the permissions arent set correct...
ubnt@ubnt:/opt/vyatta/etc/functions$ ls -la total 6 drwxr-xr-x 2 root root 38 Jun 22 17:25 . drwxr-xr-x 13 root root 4096 Jul 10 21:53 .. -rw-r--r-- 1 root root 1812 Jun 22 15:28 script-template
Changing it to chmod 755 before rolling a new firmware did no change to it...
So as the next test, I put chmod 755 /opt/vyatta/etc/functions/script-template in the script before the source command... It didnt change the result, but it altered the privileges sucessfully.
Not shure where to continue testing, I did an attempt to include all the commands that are generated when I save the wireguard interface, inbeetween "load" and "commit". Well, even with such fine config, it did not start up with a wireguard interface.
#!/bin/bash -e
BOARD=e300
if [ ! $(dpkg-query --show wireguard) ]; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
chmod 755 /opt/vyatta/etc/functions/script-template
source /opt/vyatta/etc/functions/script-template
configure
load
set interfaces wireguard wg0 address 10.0.0.2/24
set interfaces wireguard wg0 description Node2
set interfaces wireguard wg0 listen-port 50002
set interfaces wireguard wg0 private-key [redacted]
set interfaces wireguard wg0 route-allowed-ips false
set interfaces wireguard wg0 peer [redacted] allowed-ips 0.0.0.0/0
set interfaces wireguard wg0 peer [redacted] allowed-ips 0::0/0
set interfaces wireguard wg0 peer [redacted] description Node1
set interfaces wireguard wg0 peer [redacted] endpoint 192.168.5.3:50002
set interfaces wireguard wg0 peer [redacted] persistent-keepalive 1
set interfaces wireguard wg0 peer [redacted] preshared-key [redacted]
commit
exit
fi
And well, the Dashboard had nothing to do with the script.
Done some more testing and digging, learned interesting stuff I'd like to share.
The biggest knowlegde gain I had was following:
To get configure to work, you will need to use #!/bin/vbash
instead of #!/bin/bash -e
The rest of the script still works fine, dpkg doesnt care if run in bash or vbash.
On the other hand you can not use load
. Load, whatever you do, with or without a file, returns:
./install_wireguard.sh: line 16: load: command not found
Load is neither a feature that would be documented for use here... https://wiki.vyos.net/wiki/Command_scripting
All of set, delete, edit, top, up, commit should work.
So I tried the following, and to sum it up, it fails bcause some ip checking script does not exist.
The current version of my script:
#!/bin/vbash
BOARD=e300
if [ ! $(dpkg-query --show wireguard) ]; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
chmod 755 /opt/vyatta/etc/functions/script-template
source /opt/vyatta/etc/functions/script-template
configure
set interfaces wireguard wg0 address 10.0.0.2/24
set interfaces wireguard wg0 description Node2
set interfaces wireguard wg0 listen-port 50002
set interfaces wireguard wg0 private-key [redacted]
set interfaces wireguard wg0 route-allowed-ips false
set interfaces wireguard wg0 peer [redacted] allowed-ips 0.0.0.0/0
set interfaces wireguard wg0 peer [redacted] allowed-ips 0::0/0
set interfaces wireguard wg0 peer [redacted] description Node1
set interfaces wireguard wg0 peer [redacted] endpoint 192.168.5.3:50002
set interfaces wireguard wg0 peer [redacted] persistent-keepalive 1
set interfaces wireguard wg0 peer [redacted] preshared-key [redacted]
commit
exit
fi
What this script prints out if you run it (making #
before if
and fi
, for debugging):
ubnt@ubnt:/config/scripts/post-config.d$ sudo ./install_wireguard.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 141k 100 141k 0 0 134k 0 0:00:01 0:00:01 --:--:-- 151k
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 623 0 623 0 0 992 0 --:--:-- --:--:-- --:--:-- 1238
100 133k 100 133k 0 0 80823 0 0:00:01 0:00:01 --:--:-- 265k
(Reading database ... 35130 files and directories currently installed.)
Preparing to replace wireguard 0.0.20180708-1 (using .../wireguard-e300-0.0.20180708-1.deb) ...
Unpacking replacement wireguard ...
Setting up wireguard (0.0.20180708-1) ...
[ interfaces wireguard wg0 ]
sh: /vyatta-check-allowed-ips.pl: No such file or directory
Commit failed
Somehow it seems, there is a load applied anyways after the firmware upgrade and it fails with all the wireguard commands...
ubnt@ubnt:/var/log/vyatta$ cat vyatta-config-loader.log
2018-07-13 23:29:23 == begin boot-config-loader
2018-07-13 23:29:24 -- begin load
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'address' 'xxx/24'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'description' 'Gateway'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'listen-port' 'xxxxx'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'mtu' '1420'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'allowed-ips' '0.0.0.0/0'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'allowed-ips' '0::0/0'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'description' 'Gateway'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'endpoint' 'xxxx'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'persistent-keepalive' '1'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'peer' 'xxxx' 'preshared-key' 'xxxx'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'private-key' 'xxxx'] failed
The specified configuration node is not valid
Set ['interfaces' 'wireguard' 'wg0' 'route-allowed-ips' 'false'] failed
2018-07-13 23:29:24 -- load finished successfully
2018-07-13 23:29:24 -- begin commit
2018-07-13 23:31:12 -- commit succeeded
2018-07-13 23:31:12 -- teardown succeeded
2018-07-13 23:31:12 -- exiting
(I readacted the specific settings.)
I assume the load fails for the same reason as the script with all its single commands.
I havent looked into why a /vyatta-check-allowed-ips.pl
is needed and where it should be found. Maybe someone else has had similar issues...
Hi,
I did a lot of testing, changed the settings a million times over and tried to understand this hole vyatta cli...
Well, suddenly the router accepted the Script, after I removed the if ... and te fi and didnt put it back in...
This is what i currently have working:
ubnt@K51:/config/scripts/post-config.d$ sudo vi install_wireguard.sh
#!/bin/vbash
BOARD=e300
# if [ ! $(dpkg-query --show wireguard) ]; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
chmod 755 /opt/vyatta/etc/functions/script-template
source /opt/vyatta/etc/functions/script-template
configure
# load config.boot
set interfaces wireguard wg0 address 192.168.5.1/24
set interfaces wireguard wg0 description Gateway
set interfaces wireguard wg0 listen-port 50002
set interfaces wireguard wg0 private-key [...]
set interfaces wireguard wg0 route-allowed-ips false
set interfaces wireguard wg0 peer [...] allowed-ips 0.0.0.0/0
set interfaces wireguard wg0 peer [...] allowed-ips 0::0/0
set interfaces wireguard wg0 peer [...] description Gateway
set interfaces wireguard wg0 peer [...] endpoint [...]:50002
set interfaces wireguard wg0 peer [...] persistent-keepalive 1
set interfaces wireguard wg0 peer [...] preshared-key [...]
commit
exit
# fi
My assumption is, that if [ ! $(dpkg-query --show wireguard) ]; then
is somehow rejected, even though I can not see how.
Hi @Lochnair,
So today I wrote a comment in the ubiquiti forum, mourning the inclompletness on the documentation/help pages on how to write config code. Well, some nice guy pointed me to this: https://community.ubnt.com/t5/EdgeRouter/Why-are-support-articles-password-protected-now/m-p/2254283#M198274
So what these code examples do is very interesting: They take the opposite of the condition in if and use exit 1
to stop the script there, otherwise they proceed with the script. So they avoid it too, even though there is no explanation given why it is avoided, it seems to match.
So here is my adapted version which I think I am going to try for some time now. Maybe I'll add some extra logic, checking if curl and dpgk -i worked before hammering the config over it. And maybe I'll take care of extra stuff like ipv6...
Can you confirm this works on your routers?
Kind regards, Andreas
ubnt@K51:/config/scripts/post-config.d$ sudo vi install_wireguard.sh
#!/bin/vbash
#Please fill in the router model
#e50 for EdgeRouter X
#e100 for EdgeRouter Lite and EdgeRouter PoE
#e200 for EdgeRouter 8 and EdgeRouter Pro
#e300 for EdgeRouter 4
#e1000 for EdgeRouter Infinity
BOARD=e300
#The name for the interface that should be automaticly configured (use wg and a number)
INTERFACE=wg0
#The descripion for the interface
INTERFACEDESCRIPTION=Gateway
#The ip address for the interface
ADDRESS=100.64.200.3/24
#The port wireguard is listening on
LISTENPORT=50002
#your generated private key
PRIVATEKEY=[...]
#the public key of the peer to cennect to
PEER=[...]
#the description for the peer
PEERDESCRIPTION=Gateway
#the FQDN or ip address of the peer
ENDPOINT=[...]
#the port where the peer is listening
ENDPOINTPORT=50002
#the pre sherad key on the peer
PRESHAREDKEY=[...]
##################################
# DO NOT EDIT BELOW HERE
##################################
installed = "$(dpkg-query --show wireguard)"
notinstalled = "dpkg-query: no packages found matching wireguard"
echo $installed
if [ "$installed" != "$notinstalled" ]; then
echo "Wireguard is already installed."
exit 1
fi
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
chmod 755 /opt/vyatta/etc/functions/script-template
source /opt/vyatta/etc/functions/script-template
configure
set interfaces wireguard $INTERFACE address $ADDRESS
set interfaces wireguard $INTERFACE description $INTERFACEDESCRIPTION
set interfaces wireguard $INTERFACE listen-port $LISTENPORT
set interfaces wireguard $INTERFACE private-key $PRIVATEKEY
set interfaces wireguard $INTERFACE route-allowed-ips false
set interfaces wireguard $INTERFACE peer $PEER allowed-ips 0.0.0.0/0
set interfaces wireguard $INTERFACE peer $PEER allowed-ips 0::0/0
set interfaces wireguard $INTERFACE peer $PEER description $PEERDESCRIPTION
set interfaces wireguard $INTERFACE peer $PEER endpoint $ENDPOINT:$ENDPOINTPORT
set interfaces wireguard $INTERFACE peer $PEER persistent-keepalive 1
set interfaces wireguard $INTERFACE peer $PEER preshared-key $PRESHAREDKEY
commit
exit
hey @freifunkkt , it seems to me that your script (as written) works to get an edgerouter connected to a wireguard server. Am I right? How would you change it in order to set the edgerouter as a server to which my various devices can connect to? I know this is totally outside the scope of this topic so please accept my apologies in advance. Thanks!
@valantur you should get on #wireguard on freenode and ask questions like this, don't hijack a thread where someone is making progress on one topic and attempt to change the subject to something else entirely.
hey @freifunkkt , it seems to me that your script (as written) works to get an edgerouter connected to a wireguard server. Am I right?
Hi @valantur. There is no server or client in Wireguard. Both sides use the same software and need to know each other by public key (and if used, by preshared key). That said, you might need to add more Peers. Each device you want to connect needs a Peer configuration. So just iterate the section setting peers for each device that needs a tunnel. Depending on your situation regarding NAT, I think you might not configure persitant-keepalive the same way. You might need some routing additionaly. Maybe you dont want this in the same script... idk. Thats the most specific I can answer your very broad question.
I know this is totally outside the scope of this topic so please accept my apologies in advance. Thanks!
What @storrgie already wrote here, but +1.
Just a FYI:
Before you install new firmware you can do sudo wg showconf wg0 > wg0.conf and restore that part with wg setconf or addconf.
Adding wg-quick might also make the above less complex
https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
Just found out that pre-config.d is a thing. It runs before config.boot is loaded, which means that we can't download the latest vyatta-wireguard release on first boot after the upgrade since the interfaces aren't configured yet, but we can put the latest deb in a folder before rebooting into the new firmware and point a script to it.
but we can put the latest deb in a folder before rebooting into the new firmware
Is there actually some kind of hook to do this automatically? Because that would be optimal.
If not, you could always just have it grab the most recent deb at every boot and store it as something like /config/wg-latest.deb
, assuming there's a way to run stuff at boot. (I've never been one to deep-dive on customizing Ubiquiti hardware)
Or, what about using both? pre-config
to backup the system config and any wireguard configs possible, post-config
to actually download/install the .deb
and restore everything.
As for user consent, how about a node in /system
? Maybe something like system wireguard-persist yes
that can default to no
.
So, I just tried the script (manualy command by command to test) that @Lochnair wrote: https://github.com/Lochnair/vyatta-wireguard/issues/62#issuecomment-403275678
I have a ER4 (e300)
It gives a error command not found: load
looking at the script template script (/opt/vyatta/etc/functions/script-template
), load
is not defined, as well as compare
(not used in script but to check that it loads correctly)
I will be checking into this further but just wanted to post this here immediately after finding this out
Also, the download link needs to get -1
added right before .deb
as that is the filename now.
Last thing is that for automating the installation on firmware upgrade, it is not great that there is a separate tag for v2/firmware 2.x, but I will post a separate issue reference this one
Edit: I think calling /opt/vyatta/sbin/vyatta-load-config.pl
will work, will test on next firmware upgrade
all scripts/aliases that /opt/vyatta/etc/functions/script-template
sets up are located in /opt/vyatta/sbin/
so I had a look in there for scripts that might do reloading of configs
Edit2: This is the script as I have it now: https://gist.github.com/topjor/de2344fb39187adb13f455a42aa5c6a2
The scripts mentioned here use dpkg-query
to check whether WireGuard is installed. A better solution would be to use dpkg -s
, which returns a specific exit code depending on the status of the query:
if ! dpkg -s wireguard >/dev/null 2>&1; then
echo "wireguard is missing"
fi
Currently trying to figure out how to set things up properly. As far as I understood, configuration is persisted in config.boot
between Firmware upgrades. Will this lead to a failure when WireGuard is missing from the system?
@pstadler It won't cause a failure, but when the config loader can't find the WireGuard templates it'll just ignore that part of the config, thus deleting it from the running config, but it'll still be in the config.boot.
This means that if you install WireGuard after a FW upgrade, all you need to do is run load
to load the boot config into memory, and then commit
to get the WireGuard interfaces back.
Not exactly related, but maybe it can come in handy for someone: I wrote an expect
-script for upgrading WireGuard on a USG over SSH (probably works for ER as well) without rebooting the device.
I've previously tried many methods for automating / scripting this, but I gave up as I always got stuck on load
or /opt/vyatta/sbin/vyatta-load-config.pl
, where load
isn't available outside the interactive shell and vyatta-load-config.pl
always failed when run in any type of scripting mode. Tried lots of different options but to no avail 😞.
@mafredri this seems crazy. I'm currently using this on my EdgeRouter:
#!/bin/bash -e
# Wireguard on EdgeRouter
# /config/scripts/post-config.d/wireguard.sh
BOARD=e300 # ER4
CFG=/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper
if ! dpkg -s wireguard >/dev/null 2>&1; then
tag=$(curl "https://api.github.com/repos/Lochnair/vyatta-wireguard/releases" | jq -r '.[0].tag_name')
deb_url="https://github.com/Lochnair/vyatta-wireguard/releases/download/$tag/wireguard-$BOARD-$tag-1.deb"
curl -L -o "/tmp/wireguard-$BOARD-$tag.deb" "$deb_url"
dpkg -i "/tmp/wireguard-$BOARD-$tag.deb"
rm "/tmp/wireguard-$BOARD-$tag.deb"
$CFG begin
$CFG load
$CFG commit
$CFG end
fi
@pstadler I agree :(. At what point is the kernel module reloaded in your setup? My script is for updating WireGuard on a running USG without reboot.
EDIT: I'm not sure if my issue is limited to USG, my config, or running it outside of a post-upgrade scenario. Either way, nothing I've tried works (including calling load via the cmd wrapper).
I made a slightly improved version of release parsing via jq
. It handles some edge cases:
The following command sorts all releases by creation date and searches the newest releases assets for the board / fw version and returns the full download URL.
BOARD=ugw3
# OR: BOARD=v2.0-e100
ASSET_NAME="wireguard-${BOARD}"
URL="$(
curl -sSL https://api.github.com/repos/Lochnair/vyatta-wireguard/releases \
| jq -r '. |= sort_by(.created_at) | .[-1].assets | map(select(.name | contains("'$ASSET_NAME'"))) | .[0].browser_download_url'
)"
It uses simple string matching (can perhaps be improved?) which is why we include wireguard-
in $ASSET_NAME
and version in board name. It could also be changed to sort on tag, e.g. sort_by(.tag_name | sub("^v[0-9.]+-"; "") | split("[.-]"; "g") | map(tonumber))
, not sure what metric is the best.
@pstadler btw, thanks for posting that code sample. I decided to give it another try and running it with your script using slight modifications (for live upgrade) works as intended. Not sure why it suddenly works though, maybe an UGW FW update has fixed my previous issues or then there was some problem with how I was using it before.
Please have a look at the latest version of my script: https://gist.github.com/pstadler/2eb645ae829941850db2e09628fe0d85
Usage: ./wireguard.sh [upgrade|uninstall]
. When called without arguments, the latest version will be fetched and installed.
There's a logic similar to the one from @mafredri in place, to filter out releases without existing binaries. It feels like we're slowly getting there...
@Lochnair there's currently a problem with tags and versions ending with or without -1
), highlighted here. Could you make sure that future release versions and tags match?
Update: Just upgraded EdgeMax from 1.10.8 to 1.10.9 and WireGuard came up again.
I have continued developing my own script as well and have published it over at mafredri/vyatta-wireguard-installer.
Features include:
Ultimately my hope is that the combined work in this thread can be integrated into the package to support these things out-of-the box.
What I haven't figured out is how best to support the v2.0 packages for the EdgeRouter firmwares (automatic detection). I'm thinking some kind of compatibility checks (maybe kernel version?). Ideas welcome. This should be fixed in the master
branch via kernel version detection.
Speaking of compatibility checks, another nice feature would be the ability to detect if a cached package is incompatible with the current firmware / kernel, and attempt to download a newer instead, not sure how we'd accomplish that though.
I have some more Todo's/ideas listed in the readme but I don't want to go on forever with this already long comment. Cheers.
I've developed a script that will install/update WireGuard, without the need of a reboot, and preserve the package installation after a firmware upgrade. (link)
Hi,
I'd like to know if there is a possibility to include a script which restores wireguard after a firmware upgrade was done? It's no problem adding it later manually, but in general it would be better and more faultproof if it was included on install.
Ubiquiti provided a nice start. I think adapting this might be straight forward.
https://help.ubnt.com/hc/en-us/articles/204961814
Thanks for your efforts bringing wireguard to edgeos anyway.
Kind regards Andreas