Create Surfshark wireguard connection on OpenWrt easily

You have nothing to lose by trying.

All posts in this thread about script fails (@usernameTaken , @Gcholvi , and myself) speak to the same issue - inconsistent response from the SS validate pubkey routine.

It worked for me finally as of yesterday morning and has been up and stable for over 19 hours without issue, so I am not convinced the API has changed, but rather a bottleneck at SS. I just started re-running the script without changing anything and after something like 8 attempts, finally got an “OK” response to the “validate pubkey function” at which point I configured WireGuard interface and firewall, restarted network/firewall and voila!

Are you comfortable with adding a “verbose switch to the script using vi or nano?

Hi @yazdan @RuralRoots

Unfortunately, I haven't had any luck generating working conf after running the script several times. The failure still occurs at POST

where '{"code":400,"message":"Bad' 'Request"}' is returned.

After reading some of the comments from this guy generated his own public/private key pair...

Send your public key to the Surfshark API

response of
"expiresAt": "2021-10-01T01:42:09+00:00",
"pubKey": "uIePn82CDAhyZ40vCfDoGSqv8tJOiJSHhiJsdni9u3o=",
"id": "926a72f4-2e62-45fd-b96f-95f785b10dbf"
They also have, work in the same way as described above, same body, same response

After sniffing the Surfshark app, I extracted the public key added it as a parameter in a curl POST to public-keys/validate and the API payload response is like the one above which would indicate that my public key is registered with the Surfshark API. I also called the public-keys API as mentioned above and received a successful response.

However, when I call the same API and send the public key generated by the script (wg genkey command), I receive the '{"code":400,"message":"Bad' 'Request"}' response.

It seems that the Surfshark API will not accept a public key that was not generated by the app.

It has to! See: and
wg genkey | tee privatekey | wg pubkey > publickey

I am using the same private/public keys I first used several months ago when I used WG with a different provider.

The error seems to indicate a client error.

What does ls -ltr in your folder return?

Thank you for that explanation @RuralRoots Seems that I'm just having some bad luck with registering my public key with the Surfshark API for whatever reason. The output of ls -ltr is below.

 total 488
-rw-r--r-- 1 user user   1074 Dec  5 07:36 LICENSE
-rw-r--r-- 1 user user    544 Dec  5 07:36
-rw-r--r-- 1 user user    107 Dec  5 07:43 config.json
-rwxr-xr-x 1 user user   3961 Dec  5 08:28
-rw-r--r-- 1 user user   1974 Dec  5 08:44 token.json
-rw-r--r-- 1 user user  46405 Dec  5 08:45 surf_servers.json
-rw-r--r-- 1 user user  50413 Dec  5 09:01 selected_servers.json
-rw-r--r-- 1 user user    109 Dec  5 09:01 wg.json
-rw-r--r-- 1 user user 383912 Dec  5 09:02 output.txt
drwxr-xr-x 1 user user   4096 Dec  5 09:02 conf

It looks OK being you authenticated via username password with SS and they sent you your authentication “token”.

I’m somewhat confused over the timeline in your folder that seems to indicate the script ran for about 17 minutes?.

Try this. Replace the with a virgin script.
Edit the at the login function call to the curl_res=$(curl -H statement by adding -v at $url) like this $url -v).

Do the same change at wg_reg_pubkey and wg_check_pubkey. Save/Exit.

The verbose switch SHOULD show us a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition, or additional info if available.

Leave everything in your ./ folder and just rm -rf conf and run the script.

Just had a thought. If you have any wireguard instances running on any of your devices, take them down first. I don’t know if they may conflict, but . . . .?

@RuralRoots After a bit of troubleshooting, I finally have a working set of Surfshark Wireguard connection configs! Thank you for pointing me in the right direction.

To achieve this outcome, I commented out wg_reg_pubkey and wg_check_pubkey from and manually registered and my public key with the Surfshark API. I extracted the POST command from sniffing the app and replaced the public key with the one in wg.json

I noticed that the API call made by the Surfshark app includes additional parameters that are missing from your script. I'm not sure why but the API will return a 400 '{"code":400,"message":"Bad' 'Request"} unless I include all of the parameters below.

First, I register the public key with the Surfshark API (I replaced XXXXXX in the curl command below with the Cookie & Bearer Token from the app and pubkey from wg.json). Note that I ran the Surfshark client on Mac OS. The API call will be different for other operating systems.

curl -H "Host:" -H "Cookie: __cf_bm=XXXXXX" -H "content-type: application/json;charset=utf-8" -H "accept: application/json" -H "authorization: Bearer XXXXXX" -H "accept-charset: utf-8" -H "ss-variant-slugs: test_39:b;feature_1:a;feature_shadowsocks:b;test_51:b;test_54:a;feature_rotator:a;test_32:b" -H "accept-language: en-US;q=1.0" -H "user-agent: Surfshark/3.10.1 (; build:1024; macOS 12.0.1) Alamofire/5.4.3 device/desktop" --data-binary "{\"pubKey\":\"XXXXXX\"}" --compressed "" -v

Then I called the API to validate the public key. This is the same command used in the previous step except I added /validate to the end the URL.

curl -H "Host:" -H "Cookie: __cf_bm=XXXXXX" -H "content-type: application/json;charset=utf-8" -H "accept: application/json" -H "authorization: Bearer XXXXXX" -H "accept-charset: utf-8" -H "ss-variant-slugs: test_39:b;feature_1:a;feature_shadowsocks:b;test_51:b;test_54:a;feature_rotator:a;test_32:b" -H "accept-language: en-US;q=1.0" -H "user-agent: Surfshark/3.10.1 (; build:1024; macOS 12.0.1) Alamofire/5.4.3 device/desktop" --data-binary "{\"pubKey\":\"XXXXXXX\"}" --compressed "" -v

After that I ran with wg_reg_pubkey and wg_check_pubkey commented out and I now have conf files that are working in the Wireguard client. I hope this helps anyone else that may be encountering issues with the script.


Important point in retrospect, and I suspect will help the cause,

Glad you worked it out. Nobody imho, is going to change an expensive, highly engineered API without reason. SS doesn't put a limit on concurrent account devices so, ¯\(ツ)/¯ ???

In the meantime, the shell script can be confirmed "proof of concept" - everybody posting here that has tried it now has a working solution.

Hi Yazdan, can you point me in setting up the Wireshark VPN on Openwrt with Adguardhome and Dnscrypt-Proxy 2+ banip also Dns over https setup on Rpi4 4GB device???

Thanks in advance

See post 15 in this thread for prerequisites and @yazdan GitHub shell script.

Modify the config.json.sample With your SS login (email/password pair - not your VPN credentials) and rename it config.json. Run the shell script.

You will find all the SS WG servers in the ./conf folder with all your WireGuard required parameters to configure the WG interface.

I was successful to register my public key with the curl commands from usernameTaken. Now WireGuard is running fine on my OpenWRT router.
Except some websites are behaving strangely, i.e. netflix. These websites work perfectly well using the same WireGuard server using the Surfshark app.

Any ideas why this is the case? Did some settings in the command register my public key for some ad filtering feature (shadow_socks?)?

The apps include workarounds for Netflix et al - this is a WIP so don’t expect the same functionality. See

Do you think that you can lay out the steps and script you used for a Linux distro like Debian / SparkyLinux or Debian. I have been banging my head for days. Thanks

I'm also very interested in getting this to work. I've been frustrated by the slow speeds of openVPN when i now wireguard is a better option!
If i look on the webinterface, i'm just seeing "no Handshake", so i'm not quite sure where my error is.
I'm guessing it could be the keys not being generated proberly like some of the previous posts says.

I'm using a Intel NUC as my openWRT hardware, for the sole purpose of being my VPN gateway.

Where do you get that info @usernameTaken ?
I've looked in the app on my Android phone, and on my Windows computer.

I set up Monterey MacOs on virtual machine and I got surfshark app installed and connected - I also am asking where is the Cookie & Bearer Token from the app - I installed SurfShark App from Apple Store and I am connected to WireGuard. So , if anyone here can assist me with finding Cookie & Bearer Token from the app I will be most appreciative. Then I can run the script that usernameTaken has been so kind as to provide here. BTW - I am new to MacOs - so before I get stuck - is curl installed by default - and if not how do I go about installing curl ? Thanks for any assistance in advance. I have been working on this for hours - searched as many files as I know how in the Mac SurfShark app - this is a new operating system for me. Anyway, I hope someone provides this information for us all

This thread is about a shell script developed by @yazdan that is effective, but still a work in process.

Please, show me the script @usernameTaken has provided here.

Please read the entire thread to understand the context of the thread.

Maybe my terminology was a bit loose but you know what I meant - if you read my full message. I have read this thread repeatedly - obviously I am trying to register my public key - as that has been the main sticking point for many here - not just me - if you have read the entire thread. So, if you have nothing constructive to reply with - just please go silent. I have determined ( I hope that ) Cookie & Bearer Token from the app is related to JWT - or as best I can determine on my thus far. Thanks for your assistance as I had so politely asked for.

Hey guys! In order to extract the cookie and bearer token from the app, I installed Charles Proxy on my Mac and configured SSL proxying. I had to install and trust the self-signed certificate from the Charles software to be able to view contents of the SSL traffic. Here are the instructions.

You can also setup SSL proxying using Telerik Fiddler or Wireshark.

Once you have Charles (or your software of choice) setup to view SSL traffic, open the Surfshark app and login with your credentials.

During the login sequence, look for a POST method with the URL of

If you are using Charles, right click on this URL and "Copy cURL request". Paste it into a text editor. Replace the value for pubKey with the Public Key in wg.json. Then copy the command into a terminal and run it to register the public key with the Surfshark API. Then, run with wg_reg_pubkey and wg_check_pubkey commented out


Thank you so very much for your well detailed, fully understandable and most kind explanation as to how to go about arriving at ultimate success of registering one's public key. I just wish that everyone here in this Forum Thread would mirror your most admirable traits and conduct. I am a retired English Teacher and not all are adept at conceptualizing and conveying complex instructions clearly and succinctly- you have achieved both here, For that, let me be among the first to say " I am most grateful ". I had asked for a way to implement something like this on Linux ; however, I now realize that there is no Linux App for SurfShark WireGuard. Anyway, thank you once again and enjoy the Holiday Season Peace

Thank you for those kind words @directnupe I always try to remember that forums like these are intended to be communities where people can help each other. There’s no place for rudenesses or criticizing someone that doesn’t understand something. I hope that everyone was able to generate working Wireguard configs. I’m happy to help Yazden with the script when he has some free time. Have a great holiday season and stay safe and healthy!

1 Like

Dear usernameTaken,
Well actually you have made my day - thank you for your graciousness and generosity of spirit as embodied in your kind message and sentiments - and most importantly as reflected in your thoughts below :

I always try to remember that forums like these are intended to 
be communities where people can help each other.

Exactly and Amen - if you are interested in DOQ or DNS OVER QUIC ( the latest and greatest ) - check out my tutorial on AGUARDHOME here : OpenWrt AdGuard Home 101 ( DNSMASQ ) and for any others here who are intrigued by the topic

Peace and Have a Safe Holidays