Create Surfshark wireguard connection on OpenWrt easily

I can get there via https without issue using SS WG and 2 different SS openvpn instances routed through VPR.

The message is coming from your Debian update manager indicating the resource isn’t available at the time of update?

Maybe try a mirror?

Thanks for sharing @RuralRoots.

I think I'm getting closer to understanding the issue. Well, at least I know it's a config issue with PFSense and not limited to apt-get on the Debian box. Anything I do with HTTPS will hang for any local LAN IP that is routed to the PFSense wireguard interface.

The most simple test I tried is "curl" on a local LAN pc. With an open internet connection or OpenVPN on PFSense all is well, but with Wireguard there is a hang.

To independently test the wireguard config "[Interface]xxx", on my Mac I used the Wireguard client and applied it to a tunnel. It worked perfectly.

So, now I need to figure out what the heck is wrong with wireguard on PFSense.

Thank you all for the help with troubleshooting, and apologies for clogging the discussion with the chatter of a frustrated techy.

1 Like

I am trying to run this script but have run into a couple of issues. One is that special characters seem to break the script for me and I did overcome that by hard-coding the credentials and using \ as an escape character. Next, I am getting an http 429 error which is preventing me from registering my public key with Surfshark. Anybody else have these issues?

Sounds like your credentials aren’t accepted and after too many attempts, the server is shutting you down. (429 - too many responses)

First, go to SS and login in to your account. If you use

change your password to one that doesn’t use special characters. now change your credentials to your SS account login uname/pass. Do not use the credentials you generated to authenticate to a SS .ovpn server.

Try again.

1 Like

I did try to change the password and Surfshark is imposing password restrictions, so it is not possible to change a password to one with no special characters. Since the username seems to work with the @ symbol, I changed to a password with that special character.

This script does work and gives me the bearer token and renew token:



echo $surfshark_username
echo $surfshark_password

login_payload=$(printf "$login_payload_template" "$surfshark_username" "$surfshark_password")

echo "Checking Credentials"

echo "Logging in with username $surfshark_username"

login_request=curl -s -X POST "" -H "Content-Type: application/json" --data $login_payload
if [ -z "$login_request" ]
echo "Login failed. Check your username or password"
exit 1
bearer_token=echo $login_request | awk -F "[,:}]" '{print $2}' | tr -d '"'
echo $login_payload
echo $login_request
echo $bearer_token
echo "Logged in successfully"

(This wasn't my own code, but got it from:

I was able to create the token.json file manually from the other script and the original script worked fine registering and validating the public key using the existing token.json file.

Well that has absolutely nothing to with getting a SS WG instance running on OpenWrt.

If you want to run WG on your router see -
we can help.

If you are looking for help with SS SmartDNS service, you will have to ask the author at your link.

I was not able to get the script to run correctly as delivered - the token was never generated correctly. However, using snippets from the DNS site code, I was able to generate the code successfully. I was just trying to show what eventually worked for me. Perhaps there is some nuances in the API or how the curl command is written.

However, getting easytether to work with Wireguard and SurfShark seems to be my issue now. I need to configure: LAN -> EasyTether -> Wireguard. If I put Easytether and Wireguard in the same zone, then traffic seems to bypass Wireguard and go directly through the TAP interface (EasyTether). Perhaps my issue is that Wireguard is still not configured correctly in OpenWRT, although I did successfully register the public key that was generated.

Well you have me well confused now as to what you are trying to achieve. Your first post indicated you were having issues running by @yazdan.

Your reply pointed me to a script to allow you to update SurfShark’s add-on SmartDNS product.

And now you’re pointing me to an Android tethering product.

Let’s start at the beginning with and make sure you have a working WG client. Remember that SS WG authentication expires about every 6 days so you’ll need to run it on a regular basis. Get the and config.json from yazdan’s repo.

Edit config.json to reflect your SS email and password account login. Just use the plain text password (including special characters) you use to log in to your account.

Make the script executable chmod +x

Run the script ./

Post the output.

After reading this thread i'm pretty disappointed (at surfshark of course, not the efforts of people here). They mention wireguard support on their website since 2020, though conveniently leaving out Linux. After a conversation with their support they confirmed routers and manual wireguard config are unsupported.

The login rate-limit is annoying and making it difficult to debug. But if I understand correctly, even when going through the effort of sniffing their app, if key is updated once a week updating the config will be difficult to automate :frowning:

Are you using the latest It's been reliable for me. I set up a cron to Force your PubKey at 00:05 each day, and follow that up at 00:10 with just the -g switch to verify my key rolls over to another ~6 days.

I can re-boot, and the interface comes back up in service without any handshake issues. As far as that goes, I can even add a new firmware build using save settings and it comes back in service.

Here's the latest:

Dear RuralRoots,
Hello and I hope that you are well. I have been able to run the script - however, I am still at the point where I have to re-run the script every six days.
My humble and simple request of you is the following

Would you please be so kind as to put up an example of the automated  cron job 
which you describe above

Specifically as you describe here below :

I set up a cron to Force your PubKey at 00:05 each day, and 
follow that up at 00:10 with just the -g switch to verify my 
key rolls over to another ~6 days.

Forgive me for asking - but I am not that skilled with Linux - any and all assistance you would be kind enough to offer I will be most appreciative.

Thank You In Advance and God Bless

Hello @directnupe, and thank you I am well as I trust you also.

I run the script from a USB on my router so you may have to accomodate your installation accordingly.

You might also want to add a code snippet to the .sh script from an issue I posted on regarding added verbosity. It helps to verify your current update SSWG validation timespan.

Change your config.json entry "config_folder": ".", dot to the full path of your install folder ie. /mnt/shared/wgapi

In your install folder enter mkdir wg.log
vi/nano /etc/crontabs/root or in LuCI/System/Scheduled Tasks

0 0 * * * now=$(date) ; echo "$now Start of Day - wg.log" >/mnt/shared/wgapi/wg.log 2>&1  	# clear wg.log daily @ 00:00
5 00 * * * /mnt/shared/wgapi/ -f -g >>/mnt/shared/wgapi/wg.log 2>&1		# force registration daily @00:05
10 00 * * * /mnt/shared/wgapi/ -g >>/mnt/shared/wgapi/wg.log 2>&1		# run once daily @00:10 after force

Save it.

In the morning, cat wg.log should produce something akin to:

~/mnt/shared/wgapi# cat wg.log
Fri Mar  4 00:00:00 EST 2022 Start of New Day - wg.log
Log In if needed ...
Getting the list of servers ...
servers list already exist
Selecting servers ...
selected servers file exists
Generating WG Key Pairs ...
wg keys already exist
Checking pubkey ...

Authentication Keys are VALID
No need to register pubkey

You can also do logread -e SSWG if you have added the additional code snippet to the .sh script.

~# logread -e SSWG
Fri Mar  4 00:10:06 2022 user.notice SSWG: RUN DATE:2022-03-04T00:10:06-05:00   KEYS EXPIRE ON: 2022-03-11T05:10:05+00:00

The Script (Yazdan) works well for me. The only thing I changed in the script was instead of https, I used http. However, the data from the conf file (e.g., public, private keys) does not work with pfsense (wireguard). I use pfsense (wireguard) with Winscribe and VPN unlimited currently. They work well. For some reason, surfshark wireguard does not work with pfsense for the moment. Thanks for the script, though.

Thank you very much Rural Roots - I always run OpenWRT with exroot, so I will follow your instructions to the exact letter. I truly appreciate your taking the time and having the generosity of spirit to impart and share this knowledge with me. Stay Safe - and I stated this before, the Greater OpenWRT owes you a considerable degree of gratitude as you have always assisted forum members with questions across a wide range of issues and topics.
Peace My Brother -
And thank you most importantly for giving me the opportunity to learn

1 Like

Yes with some more tinkering I made it work. Also put some improvements in the script but it's not finished yet :D. It seems there are some quirks like when you get a new token and immediately register a pubkey it doesn't work. Also if you register the key again you get empty response. I'm not sure if all servers are suitable or how the selection is supposed to work? But i can generate configs, and manually configure my wireguard interface.

I'm not sure about writing uci commands. I don't fully understand wireguard and VPNs in general, so would you create a peer for all remote hosts? And then use routing etc to divide traffic over different peers? Or would each connection use a random peer? Also why do you generate a peer for with a static pub key?

Not sure if it is worth fully automating, i will monitor it for a while and check how often servers change.

You have to remember that this is the API that is handling/interacting with all the various apps/platforms that SS provides a WG option. They tend to be transitory by their nature. It’s not intended to support/allow us to use a manual WG interface on our routers that at this point they don’t support. Them’s the quirks you come across as you’ve found.

Your Authentication Token token.json only has a limited lifespan (about 30 minutes~).

That’s why the -g switch gives you an unauthorized response beyond that until you get a new token.json using the -f -g switch.

So, bottom line - run once daily with -f -g switch, run once more within that ~30 minute window with just the -g switch to confirm the update.

SS has promised to give us a WG manual install for routers first quarter of 2022. I’ll believe it when I see it, but at the moment, this script works exceptionally well for me.

1 Like

Dear RuralRoots,
Hello and I hope that you are well. I took my first crack at setting up the script as you were kind enough to outline in your previous post / instructions. I ran across a few speed bumps. I think I went off course here -

You might also want to add a code snippet to the .sh script from 
an issue I posted on
regarding added verbosity. It helps to verify your current update 
SSWG validation timespan.

Q1 -Would you please indicate where to add the snippet in the script - you know - on which line ?

I just caught this - I did not change :

config.json entry "config_folder": ".", dot to the full path 
of your install folder ie. /mnt/shared/wgapi

I will correct this - I used install folder /mnt/shared/wgapi as I used exroot on usb just as you do in your directions

Q2 - Lastly - how do I get to this point below on the shell command prompt ?

~/mnt/shared/wgapi# cat wg.log

I can't cd to this point - once again I am an advanced novice at best - please bear with me


I will fix the folder full path error and hopefully hear from you regarding the other matters.

Thanks in your assistance - and hopefully I am getting closer to the top of the hill

Add code snippet to after line 122

cd /mnt/shared/wgapi

Change /mnt/shared/wgapi anywhere you see it in my instructions to wherever on your overlay you placed the

Replace the . to the same value.

~/mnt/shared/wgapi was just an example I used because that is where I placed my folder.

Dear RuralRoots,
Thanks -

are the snippet ( s ) - I was unable to see / find which your post you reference regarding

a code snippet to the .sh script from an issue I posted 
regarding added verbosity.

I assiduously and diligently searched for your post to no avail - should I add ( after line 122 )

-v   /  -g  /  -f 

I believe that  -v  is the only one I need  - am I correct ? - 
or is something else totally different required ?

I created my install folder as below

mkdir -p /mnt/shared/wgapi/

and my log file as below

mkdir -p /mnt/shared/wgapi/wg.log/

I corrected my config.json entry "config_folder": ".", dot to the full path to below :

    "config_folder": "/mnt/shared/wgapi/",

Finally given all the information above - should I just

cd /mnt/shared/wgapi

and from there

cat /wg.log

Thanks My Brother for the guidance

PS - Are You Referring to your fork ?

With regards to the code snippet to the .sh script ?

I found your fork and issue your raised here

added this code snippet to after line 122

        echo "TODAYS DATE"              # Display Run Date
        echo ""${now}""                 # and Time
        echo ""                         #
        echo "KEYS EXPIRE ON:"          # Display Authentication Token
        echo "${expire_date}"           # Expiry Date and Time
        logger -t SSWG "RUN DATE:${now}   KEYS EXPIRE ON: ${expire_date}"       # Log Status Information

You can remove the log file. It is set up in the crontabs/root entries.

You won't find any logs until the cron jobs run. You can copy the cron entries:
/mnt/shared/wgapi/ -f -g >/mnt/shared/wgapi/wg-f.log 2>&1
/mnt/shared/wgapi/ -g >>/mnt/shared/wgapi/wg-g.log 2>&1
run each seperately 5 minutes apart and you should see the 2 logs populate.