You can choose wireguard servers randomly off a list

Post new topic   Reply to topic    DD-WRT Forum Forum Index -> Advanced Networking
Author Message
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Mon Sep 13, 2021 16:33    Post subject: You can choose wireguard servers randomly off a list Reply with quote
Here is a way you can hook a dd-wrt wireguard client up to a server randomly chosen off a short list. As presented here, the approach is specifically for routers that are rebooted at regular intervals, with any server change becoming effective when wireguard starts after the boot.

It has been tested on build 46816 and will not be quite right on much older builds. (The info in nvram variable oet1_ipaddrmask here was handled differently before.) I suspect it is fine on builds since then (through the date of this post), but I don't actually know. If changes are needed for newer builds, someone with a clue will need to chime in.

Its best, of course, if you are enough up on shell scripting and awk to follow the code before actually trying it, as I can't guarantee that my notes below are clear enough for plug-n-play users.

In any case, what I do is include the code below in GUI>Administration>Commands>Shutdown (nvram variable rc_shutdown). The approach changes servers by editing the nvram variables that specify the wireguard peer's (server's) name, endpoint IP, and peer key and the wireguard interface's CIDR IP-address subnet and public and private keys. Of course editing the interface keys is not necessary if you have the same key pair registered with all the servers, but I lean to the view that this would be poor security practice, so the code here is set up to edit those keys. These nvram edits then determine what server is used beginning the next time wireguard is started, presumably at the next boot. (Thjis is not quite the original version of the code that was posted. See my third and fourth posts, fourth and fifth posts of the thread, for a pair of tweaks made in pursuit of better randomness, tweaks that have been incorporated here.)
Code:
# random oet1 server next boot
awk "function nv(var,val){printf \"nvram set oet1_%s='%s'\n\",var,val}
BEGIN{nLine=3; R=$(hexdump -n2 -e'"%u\n"' /dev/urandom)"'
      iLine=1+int(nLine*R/65536)}
NR==iLine {
  printf "if [[ $(nvram get oet1_namep0) != %s ]]; then\n",$1
    nv("namep0",$1); nv("rem0",$2); nv("peerkey0",$3)
      nv("ipaddrmask",$4); nv("public",$5)
        nv("private",$6)
    print "nvram commit"
  print "fi"
}' <<EOF | sh
Name1 Endpoint-IP1 xxxxxxxxxxxxxxPeerKey1xxxxxxxxxxxxxxxxxxxxx= \
  InterfaceIP/24 xxxxxxxxxInterfacePublicKey1xxxxxxxxxxxxxxx= \
    xxxxxxxxxxxxxxInterfacePrivateKey1xxxxxxxxx=
Name2 XX.XX.XX.XX 3124908751204897512045851243134123445434555= \
  10.0.1.23/19 34958710w9fjdprou102efjdf01erdlf34234343444= \
    sfg89234fgwsfkg24rtwsfif89rjqwfqsdf29rfdd33=
Name3 YY.YY.YY.YY 24rasffg9824rjasfg2309rfasdofk24rasdfasdfdd= \
  10.0.220.27/24 23q4rasodfj2q9fjasdfjasderk2128934dfwsd2344= \
    KDFH+78ysdfasdcgjwerfasdfsdfasdfasdf24r2333=
EOF
The apparent triple quote at the end of the BEGIN line is actually a double quote followed by a single quote. Likewise the -e'"%u\n"' earlier in that line contains double quotes inside of single quotes. (Isn't typography a pain?)

As shown here, the code is specific to interface oet1 (with one peer) and a list of three (variable nLine) servers - lines beginning with Name1, Name2, and Name3 here, so modify as appropriate. Note that "\" at the end of a line is a continuation character, so groupts of three apparent config lines here are each seen internally as one line. The three such individual server lines should contain the info indicated by example in my Name1 line, so the labels you see there are placeholders, not headings. You can replace "| sh" with "| cat" to do preliminary testing by running the code in the CLI, as that will just print the nvram commands to the terminal instead of executing them.

Consult the wireguard client setup guide (see wireguard sticky at the top of this forum) and your VPN provider's documentation for getting the parameters for individual servers. Remember that you'll need to have each server registered with your VPN provider. If you're unsure about these server parameters, get one server set up the conventional way in the GUI and verify that it's working. Then in the CLI do
Code:
nvram get oet1_namep0
nvram get oet1_rem0
nvram get oet1_peerkey0
nvram get oet1_ipaddrmask
nvram get oet1_public
nvram get oet1_private
to see what items need to be edited into the server list in the code above to include that server as one of the nLine choices. Comparing the values returned with what you see in the GUI should help.

I have this working smoothly with four AzireVPN servers now. With Azire in particular, you don't want so many servers in the list that you risk going many weeks without any particular server being used, because Azire quietly deregisters you automatically from each registered server after some unknown number of weeks. Yes, I've asked them how long. No, they won't tell. They feel it would be a security risk to disclose it. As to why bother for just four servers? That's your call, but for me it's about trying to annoy the advertiser trackers who think they can determine where I live based on watching my IP address over time. And it just seemed interesting to try to do.

_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.


Last edited by SurprisedItWorks on Thu Sep 23, 2021 21:33; edited 3 times in total
Sponsor
egc
DD-WRT Guru


Joined: 18 Mar 2014
Posts: 8330
Location: Netherlands

PostPosted: Mon Sep 13, 2021 16:53    Post subject: Reply with quote
Congrats Nice work!

I use Mullvad and Keepsolid, Mullvad has many servers and sometimes one of those is down for maintenance so you will lose your connection.

So I already worked on making a "fail group" for the WG interface with a connection watchdog so if one server goes down it will start up the next in the fail group.
(there will be a randomization setting to randomize the first server in the fail group but that will be later this year)

But I have to do some more testing and of course it might not be deemed good enough to incorporate in the regular builds so in the mean time we have your excellent solution, Thanks!

_________________
Routers:Netgear R7800, R6400v1, R6400v2, Linksys EA8500, EA6900 (XvortexCFE), E2000 (converted WRT320N), WRT54GS v1.
WireGuard Documents & Guides:https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327397
OpenVPN Documents & Guides: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327398
IPSET: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327261
Install guide R6400v2:http://forum.dd-wrt.com/phpBB2/viewtopic.php?t=316399
Install guide R7800: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=320614
Forum Guide Lines (important read):https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=324087
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Mon Sep 13, 2021 17:29    Post subject: Reply with quote
egc wrote:
I already worked on making a "fail group" for the WG interface with a connection watchdog so if one server goes down it will start up the next in the fail group.
(there will be a randomization setting to randomize the first server in the fail group but that will be later this year)
Hey, that's great! Looking forward to it! It will sure make it feel safer routing DNS through wireguard. Right now you can use dnsmasq's timeout/fallback to a secondary DNS server with a nonwireguard route, but the 5s timeout on every DNS request is seriously painful. A nonconnect timeout at the wireguard level would be way cleaner, as the system would only have to suffer the timeout/reconnect delay once.
_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Sat Sep 18, 2021 18:17    Post subject: Reply with quote
With the OP code as originally shown, the default behavior of srand() seemed to be landing me on the same server every day, so I'm replacing the two lines
Code:
awk "function nv(var,val){printf \"nvram set oet1_%s='%s'\n\",var,val}"'
  BEGIN{nLine=3; srand();iLine=1+int(nLine*rand())}
with the three lines
Code:
awk "function nv(var,val){printf \"nvram set oet1_%s='%s'\n\",var,val}
  BEGIN{nLine=4; srand($(hexdump -n2 -e'"%u\n"' /dev/urandom))"'
        iLine=1+int(nLine*rand())}
to be more sure of randomness. The point is to give a random argument to srand(), with the rest of it just being a minor adjustment of the quoting to make things work as intended.

Note that the apparent pair of "triple quotes" after the hexdump -n2 -eis actually a pair of double quotes inside of a pair of single quotes, so ' "%u\n" ' without the spaces.

I'm editing the OP so that it reflects the current version of the code.

_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Thu Sep 23, 2021 21:22    Post subject: Reply with quote
Well, I became less than convinced that things were really coming up random still, so I decided to cut out the ultimately pointless use of awk's srand() and rand() functions, particularly as the proper choice of seed (what range?) was a mystery inadequately addressed by what I could dig up via the usual google/Startpage/DuckDuckGo research. So, the two lines
Code:
BEGIN{nLine=4; srand($(hexdump -n2 -e'"%u\n"' /dev/urandom))"'
      iLine=1+int(nLine*rand())}
have now become this:
Code:
  BEGIN{nLine=4; R=$(hexdump -n2 -e'"%u\n"' /dev/urandom)"'
        iLine=1+int(nLine*R/65536)}
The OP will be updated shortly to reflect this edit.

I apologize for my impatience in posting the whole thing too soon. I wanted to get it up while it was still fresh in my mind, but I'm not as young as I used to be (who is???), and the probability of me getting it precisely right early on seems to be decreasing with age. If it weren't for the age excuse, you'd think I'd have awk down by now, as I've used it now and then for nearly 40 years.

_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.
kernel-panic69
DD-WRT Guru


Joined: 08 May 2018
Posts: 10581
Location: Texas, USA

PostPosted: Thu Sep 23, 2021 21:50    Post subject: Reply with quote
Keep up the good work!
_________________
Official Forum Rules, Guidelines & Helpful InformationFirmware FAQInstallation WikiWhere Do I Download Firmware‽
DON'T use Chromium-based browsersRTFM/STFW TL;DR is NOT an excuse. • Why Should I Care What Color the Bikeshed Is‽
Please DO NOT PM me with questions; Ask in the forum. ---------------------- Linux User #377467 counter.li.org / linuxcounter.net
egc
DD-WRT Guru


Joined: 18 Mar 2014
Posts: 8330
Location: Netherlands

PostPosted: Fri Sep 24, 2021 9:12    Post subject: Reply with quote
I came up with the following but have yet to test it:

Code:
#random number between 0 and 10
tunnels = 4  # maxtunnels + 1
mytunnel=$tunnels
while [[ $mytunnel -ge $tunnels || $mytunnel -eq 0 ]]; do
   mytunnel=$(head -10 /dev/urandom | tr -dc "0123456789" | head -c1)
done

_________________
Routers:Netgear R7800, R6400v1, R6400v2, Linksys EA8500, EA6900 (XvortexCFE), E2000 (converted WRT320N), WRT54GS v1.
WireGuard Documents & Guides:https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327397
OpenVPN Documents & Guides: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327398
IPSET: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=327261
Install guide R6400v2:http://forum.dd-wrt.com/phpBB2/viewtopic.php?t=316399
Install guide R7800: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=320614
Forum Guide Lines (important read):https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=324087
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Fri Sep 24, 2021 15:56    Post subject: Reply with quote
egc wrote:
I came up with the following but have yet to test it (Update 3 Oct 21: It works great!):

Code:
#random number between 0 and 10
tunnels = 4  # maxtunnels + 1
mytunnel=$tunnels
while [[ $mytunnel -ge $tunnels || $mytunnel -eq 0 ]]; do
   mytunnel=$(head -10 /dev/urandom | tr -dc "0123456789" | head -c1)
done

I see where you are going with this (but put a -n after head), but it's kind of doing things the hard way (as all good programming explorations do initially Very Happy ).

I think what I have currently is working as intended. Certainly there is no issue with the hexdump thing to get a random unsigned int in 0..65535, as that's something I've used in the past for other purposes, and it's well tested. It's the cleanest way in our shell that I've ever found to get a random integer in the range 0 <= integer < 2^(8*n). My subsequent little awk trick mangles it into 1..10.

FWIW, another easy way programmingwise to get there is to use the hexdump (on three bytes instead of two if you favor super accuracy in the probabilities) to get an unsigned int in sh and then use shell arithmetic to take it mod 10 to get a random integer in 0..9. Obviously add 1 to get 1..10. And you can do other transformations. For example, here's a random sleep between 2m and 132m in 5m steps, with the possible outcomes of roughly equal probability (for better uniformity of probabilities, get 2, 3, or 4 bytes in the hexdump):

sleep $((2+5*($(hexdump -n1 -e '"%u\n"' /dev/urandom)%27)))m

_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.


Last edited by SurprisedItWorks on Sun Oct 03, 2021 22:10; edited 1 time in total
timmytee
DD-WRT Novice


Joined: 27 Sep 2021
Posts: 3

PostPosted: Thu Sep 30, 2021 1:14    Post subject: NordVPN Reply with quote
Could this work with NordVPN? I would like to give a list of VPN servers to my dd-wrt router, to change the server connection daily/weekly/monthly, or on demand.

There could be a button in the dd-wrt interface that allows "choose next server in the list", OR "choose the server in box#3" -- feature request....
SurprisedItWorks
DD-WRT Guru


Joined: 04 Aug 2018
Posts: 1247
Location: Appalachian mountains, USA

PostPosted: Thu Sep 30, 2021 2:25    Post subject: Re: NordVPN Reply with quote
timmytee wrote:
Could this work with NordVPN? I would like to give a list of VPN servers to my dd-wrt router, to change the server connection daily/weekly/monthly, or on demand.

There could be a button in the dd-wrt interface that allows "choose next server in the list", OR "choose the server in box#3" -- feature request....

NordVPN's wireguard service is available only through their app. It is not compatible with the dd-wrt client.

If you want a random NordVPN OpenVPN server on each dd-wrt boot, however, that's pretty easy, or was the last time I used Nord, around three years ago. The key is that Nord, at least at that time, used identical certificates for every server, at least here in the US, even though they publish them individually on their site. If that's still true, you can change Nord servers any time by just changing the server name on dd-wrt's OpenVPN page. If that works for you, find my discussion of doing the random thing for AirVPN in my how-to post linked in my sig below. That part of the post is not specific to Air, except that where I specified port 443 for Air, you can use Nord's default port of 1194. I'm going from faded memories here, so YMMV.

_________________
Six Linksys WRT1900ACSv2 routers on 46816: VLANs, VAPs, NAS, client mode, OpenVPN client (AirVPN), DDNS, wireguard servers and clients (AzireVPN), three DNSCrypt DNS providers (incl Quad9) via VPN clients.
Display posts from previous:    Page 1 of 1
Post new topic   Reply to topic    DD-WRT Forum Forum Index -> Advanced Networking All times are GMT

Navigation

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum