pia-foss / manual-connections

Scripts for manual connections to Private Internet Access
MIT License
636 stars 169 forks source link

OpenWrt compatibility? #5

Open Jorman opened 4 years ago

Jorman commented 4 years ago

Hi, I set-up a wireguard connection with the openwrt interface, I extracted data and manually configured the wg interface. I just see this work-in-progres, I update xargs, jq and curl to my openwrt router and I tried to run get_region_and_token.sh but is not able to run printServerLatency function, I think.

Is possible to make the script compatible with openwrt? With a functional script will be possible make some script to launch after a connection to take the port-forward or other things. The best thing would be if you plan to make an entire "app" for openwrt to install with opkg, to manage port-forward too.

What do you think about it?

g00nix commented 4 years ago

@Jorman Thank you for your ticket!

OpenWRT is definitely on our roadmap. DD-WRT too. Our QA team is currently looking into this, however I can not promise a date at this point. I think this ticket should stay open till we test this out enough to add documentation and fixes for router distributions.

Having an app in opkg is a good idea, however that should be a different project.

Jorman commented 4 years ago

@g00nix Thank you for your reply. I've no rush, I just switched from openvpn to wg only few days ago, that was only a test but wg run so good, the max speed is 3 time faster than openvpn, so quite good for me! I can't help, I'm not on QA team and maybe my limited skills with bash can't be very helpful, but if you need some "real" test I can help.

Thanks for your support.

J

g00nix commented 4 years ago

I see from the official OpenWRT documentation for WireGuard that it does not rely on wg-quick, but on uci to configure WireGuard. The documentation also provides commands to change firewall settings in order to enable and secure the VPN connection.

This might mean that the scripts must be rewritten for OpenWRT. I will keep this on my radar and update the ticket as soon as I have new information.

Jorman commented 4 years ago

Thanks, actually I configured wireguard from luci (that is a "visual" uci) I followed a guide for another provider but is the same, only keys change (https://www.vpnunlimitedapp.com/help/manuals/open-wrt-wireguard-setup), so I manually created one interface and configured with the requested data. Personally I use wg only for some deviced on lan, so I've to use VPN and WAN Policy-Based Routing from https://github.com/stangri/openwrt-repo and I have to configure the firewall wg_test wg_test1

A dedicated app will be helpful to choose the right and best server, to keep alive connection, to take port-forward, to change periodically the server with the best one and so much.

J

lioux commented 4 years ago

I've just added a pull request to get get_region_and_token.sh working on OpenWRT and shell interpreter implementations other than bash(1).

g00nix commented 3 years ago

We created a branch where we will start to add scripts and documentation specific to OpenWRT: https://github.com/pia-foss/manual-connections/tree/openwrt_testing/extra/openwrt

benisai commented 3 years ago

@g00nix - do we have an update on the OpenWRT scripts? I didn't see any new files in the extra/openwrt. Much appreciated.

g00nix commented 3 years ago

@g00nix - do we have an update on the OpenWRT scripts?

Not yet.

Jorman commented 3 years ago

I've, but I've to find some time, if you want I can post here a little guide, but have to be adapted, maybe your configuration is different

benisai commented 3 years ago

I've, but I've to find some time, if you want I can post here a little guide

That would be great!

Jorman commented 3 years ago

Ok, let's try this: I had this working on OpenWrt 18.06.4, so maybe you've to adapt the following instructions. Now with a new powerful nas I created a docker to handle wg connection with desired programs, so I don't need more this

Legend: pf -> port-forward wg -> wire-guard

What this set of files and configuration do? This's my personal way to get pf from pia and set to a specific ip within my lan, to do that I also use VPN and WAN Policy-Based Routing module on OpenWrt, you can unset the pf to specific ip and this, in theory, enable pf to router IP, but I never tried that.

So the logic of this set of scripts is:

  1. Check that wg connection is up and running
  2. Take the pf from pia
  3. Launch the side-script (if exist)
  4. Keep checking if connection go down or the pf expire

What you've to do before make this work? You've to set-up and make it running a new Interface on OpenWrt router with WireGuard protocol, in this example the interface name is TEST_WG_PIA wg You also need to have ssh access to your router with WinSCP or the program do you prefer

How to make it works?

  1. Download and extract these three files inside /root on your OpenWrt Router OpenWrt-Pia.zip
  2. Edit wg_watchdog.sh, to reflect what your configuration needs, reads all comment inside the file to know what you've to edit, pay attention to: a. ip_to_forward the ip where you want to set firewall rules in order to have pf working. b. wireguard_interface_name the WireGuard interface name you created before
  3. wg_watchdog.callback is the side-script, so the main script launch .callback file, if exist, with the same basename of the main script. In this script you can place any script you want to be executed after the main script has been executed correctly, note that the main script send two arguments to .callback script pf and VPN public ip, and finally the main script also save a file with pf inside it to /tmp/pia-wg/pia-port-forward. So, if you look at my .callback file, you will notice that I use qBittorrent on the nas 10.0.0.100, then over one ssh connection to my nas (that you've to set up one by hand) I put the pf directly to qBittorrent through qbt program. FYI I also have one script on nas side, so when qBittorrent start, the script check that the pf inside the router is the same and if different change it.
  4. Go to System -> Startup and put this on Local Startup section sleep 15 & /bin/sh /root/wg_watchdog.sh &

Now, after a reboot, the script will wait 15 seconds then start (note that maybe you've to set a longer time, depends on your router speed/connection) then the script will always check your wg connection and if lost bring it up again and get/set pf to desired ip. In theory, you'll get more info inside https://<your-ip-router>/cgi-bin/luci/admin/status/syslog

I know that seems quite advanced but is not too hard to set-it up, maybe can be used to start a new fork with a collection of .callback scripts

Let us know if you can make it works for your expectations

J

brimur commented 3 years ago

Hi @Jorman, I used your script and was able to create a connection to PIA, I am getting an IP but I think I did something wrong. I cant route traffic over the connection. Even doing a traceroute out that interface fails...

Btw I installed the VPN policy based routing and set the following but I get the same result whether it is enabled or disabled

image

root@OpenWrt:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br-lan state UP group default qlen 1000
    link/ether 00:0c:29:b2:a6:44 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:b2:a6:4e brd ff:ff:ff:ff:ff:ff
    inet <WAN>/24 brd <WAN>.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feb2:a64e/64 scope link
       valid_lft forever preferred_lft forever
4: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:0c:29:b2:a6:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.201.1/24 brd 192.168.201.255 scope global br-lan
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feb2:a644/64 scope link
       valid_lft forever preferred_lft forever
9: PIAWG: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 10.14.204.245/32 brd 255.255.255.255 scope global PIAWG
       valid_lft forever preferred_lft forever
root@OpenWrt:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         <WAN>.82.1     0.0.0.0         UG    100    0        0 eth1
10.14.204.245   *               255.255.255.255 UH    1      0        0 PIAWG
<WAN>.82.0     *               255.255.255.0   U     100    0        0 eth1
192.168.200.0   192.168.201.2   255.255.254.0   UG    100    0        0 br-lan
192.168.201.0   *               255.255.255.0   U     0      0        0 br-lan
root@OpenWrt:~# traceroute 1.1.1.1 -i PIAWG
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 46 byte packets
 1traceroute: sendto: No error information
root@OpenWrt:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         <WAN>.82.1     0.0.0.0         UG    100    0        0 eth1
10.18.152.131   *               255.255.255.255 UH    10     0        0 PIAWG
<WAN>.82.0     *               255.255.255.0   U     100    0        0 eth1
192.168.200.0   192.168.201.2   255.255.254.0   UG    100    0        0 br-lan
192.168.201.0   *               255.255.255.0   U     0      0        0 br-lan
root@OpenWrt:~#
Jorman commented 3 years ago

Hi @brimur this's a "side" argument, because once you have connection established you can do whatever you want. What is your purpose? I just note that I don't mentioned my primary purpose, so I used to use all the system to forward the pia connection only through one ip over the lan, maybe I've to update the post, but the post only explain how to get the connection and the pf working, so is quite good. If you want, like me, use the pia connection only for one ip over the lan, you've to use VPN policy based routing, like you did, but you also have to configure it in the right way, that's not so easy, tonight I watch on my router and I look if I've all the old configuration, if not you will have to look at developer page, where you can find some extra tips in order to do that. I remember that was not easy for me too.

Jorman

brimur commented 3 years ago

Thanks. I solved my issue. :)

Jorman commented 3 years ago

Glad you solved. You can share your solution here, if you want, maybe some users will find useful information

J

g00nix commented 3 years ago

Has anybody tried to migrate the bash scripts to ash to see if we can make this work from the CLI? So mostly getting the region and the token and starting WireGuard as described here: https://openwrt.org/docs/guide-user/services/vpn/wireguard/client

milahu commented 3 years ago

Has anybody tried to migrate the bash scripts to ash

problems

i did a rewrite of the pia-foss bash version, but never published it, since it does NOT run on my openwrt router since i could not get wg-quick running on openwrt's posix shell

but my talking to PIA servers works in posix shell with https://github.com/milahu/vpn-client-pia-wireguard-posix-shell

added features * select server by region * test DNS * test port forwarding (tcp, udp) * open PF port in local firewall (this is needed at least on nixos) * refactored bash code, "prettier" output, "better" CLI (commands: connect, regions, servers) alternatives * python, nodejs: waaaay too heavy for an openwrt router * rust: could be the simplest solution ... use some libraries (http, json, wireguard) and compile with [rust-cross](https://github.com/japaric/rust-cross) * problem: rust binaries are [much larger](https://github.com/johnthagen/min-sized-rust#removing-libstd-with-no_std) than C binaries, which use only libc * [vopono](https://github.com/jamesmcm/vopono) already works with PIA, but only OpenVPN (booh) * most existing [rust wireguard clients](https://github.com/topics/wireguard?l=rust&o=desc&s=stars) seem too complex .. ~~personally i would start with [wg-bond](https://github.com/cab404/wg-bond) and reduce it to a minimum~~ * https://docs.rs/cmd_lib/1.2.1/cmd_lib/ to use shellcode in rust * golang * C - can produce very small binaries
g00nix commented 3 years ago

Why rust and not go? It should be light enough.

milahu commented 3 years ago

Why rust and not go?

personal taste. but of course, go works too : )

edit: https://github.com/digineo/go-uci (work in progress) (but probably we can just use the uci binary)

also: https://openwrt.org/docs/guide-user/services/vpn/wireguard/client

Jorman commented 3 years ago

@g00nix why ash? Why not create a package, for example like this https://github.com/openwrt/packages/tree/master/net/acme (is only one example) and then create a reference uci app, to follow the example above https://github.com/openwrt/luci/tree/openwrt-21.02/applications/luci-app-acme Or do you think there's a better and simple way?

J

milahu commented 3 years ago

why ash?

posix shell (sh) in general

root@OpenWrt:~# ls -l /bin/sh
lrwxrwxrwx    1 root     root             7 Dec  6  2020 /bin/sh -> busybox

root@OpenWrt:~# bash
-ash: bash: not found

as alternative to the rust/go route, we could compile curl with connect-to support, and port wg-quick to posix shell. could be cheaper/simpler in terms of binary size

milahu commented 3 years ago

compile curl with connect-to support

this works already

root@OpenWrt:~# name=googlecom; ip=$(resolveip -4 google.com); \
curl -s --get --connect-to "$name::$ip:" http://googlecom/ | head -n1
<!DOCTYPE html>

the unsupported curl option is --no-progress-meter which only affects the "pretty" interface

sorry for the noise .__.

so the actual challenge is

wg-quick is written in bash

→ unmerged wg-tools/src/wg-quick/posix.sh

g00nix commented 3 years ago

You don't actually need --connect-to cause you can also use the Let's Encrypt certificate on the domains you find with this command:

curl -s "https://serverlist.piaservers.net/vpninfo/servers/v6" | head -1 | jq | grep dns

If you curl any of those on 1337 you will get a response from a WireGuard API on an empty server. We can also create another endpoint that deliver only the FQDNs in a format that is easier to parse by a ash script and without having a requirement for jq.

So this would solve the curl issue and would also simplify the script. Regarding bash, OpenWRT by default comes with ash, which has a smaller footprint.

You also don't need wg-quick cause luci already has support for wireguard here: https://openwrt.org/docs/guide-user/services/vpn/wireguard/client

@Jorman my first instinct is to go for ash cause I don't have experience writing uci apps. Thank you for the advice! I will have a look at this! Anyway even for uci everything I wrote above still stands. You don't need wg-quick and you don't need --connect-to.

Jorman commented 3 years ago

"Compiling" the app is pretty easy for you that are a very lot more good than me in programming. If you look at the makefile you can also see that you can specify all the dependencies, and all is already bin/sh Then the luci app I think is html or js, depending https://github.com/openwrt/luci/blob/openwrt-21.02/applications/luci-app-wireguard/luasrc/view/wireguard.htm Maybe a good starting point is wireguard?

J