pia.sh - Fully featured unofficial Linux PIA client written in bash

edited November 19 in Linux VPN Setup Posts: 41
Hi all,
    Just a heads up if anyone wants a fully featured client that works on any Linux:
Linux pia client v 0.2

Any feedback or suggestions welcome!
   Cheers
Post edited by d4rkcat on
«1

Comments

  • Posts: 112
    @d4rkcat I haven't tested this (nor an Arch user) but thank you for this! Hope others can find it useful.
  • edited November 4 Posts: 1
    arch user running your script. works like a charm, thanks much.

    feedback:
    consider adding a start at boot switch (maybe by setting a crontab).

    ┈┈┈┈┈┈▕▔╲
    ┈┈┈┈┈┈┈▏▕
    ┈┈┈┈┈┈┈▏▕▂▂▂
    ▂▂▂▂▂▂╱┈▕▂▂▂▏
    ▉▉▉▉▉┈┈┈▕▂▂▂▏
    ▉▉▉▉▉┈┈┈▕▂▂▂▏
    ▔▔▔▔▔▔╲▂▕▂▂▂▏
    Post edited by ratJuice on
  • Posts: 298
    i think that's a nice bit of work: the script.  the README example shows a number to select a server but it looks to me you're meant to select a server by name, yes?

    the quoting on the echo to create the resolv.conf contents looks mad complicated. have you encountered the use of inline input redirection (aka "here" input) ?

    echo begin!

    cat << _Unique_Text_Symbol_ > output-file-name
    text line 1
    text line 2
    and so on
    last text line
    _Unique_Text_Symbol_

    echo done!

  • edited November 9 Posts: 41
    @sn0wmonster
    Cheers bud, script should work on any linux distro with a bash shell, and also works automatically (installing dependencies) on debian and arch based distros (ubuntu, kali, mint, antergos etc etc). For any other linux just install openvpn and ufw and it will work.

    @ratJuice
    Thanks for trying it out, pushed a few updates since you posted so you might want to git pull and run with a -u to make sure you are compatible with the new version. I don't plan to implement any startup methods as the script is designed to be run in a terminal so you can shut down the VPN and restore all settings whenever you like and also see all the relevant information such as forwarded port.

    @martouf
    Thanks for taking a look at the script. The -s switch is meant to be run with a number, just like in the example. It is much quicker than typing in the full name of the location. You can see the numbers with the corresponding full place names by running with -l switch. About the echo for the resolv.conf, it isn't complicated at all it is called triple quoting and it is how i prefer to echo multi line strings. Whichever way works for you is cool, that's whats so great about bash, many ways to skin a cat:

    echo '''look
    at
    my
    lines'''
    echo -e "look\nat\nmy\nlines" echo bG9vawphdApteQpsaW5lcwo= | base64 -d
    Post edited by d4rkcat on
  • edited November 19 Posts: 41
    Have just completed the client in that it has all of the same features as the official one, with the added advantage of working on any linux with a bash shell, openvpn and ufw installed.
    Completely open source and under 500 lines of easy to understand bash code.
    Enjoy!
    Post edited by d4rkcat on
  • Posts: 41
    v 0.2 Changelog:
    • PIA MACE
    • Internet Killswitch
    • Improved code optimization and readability  
    NOTE: users of previous versions must run with -u once after updating to make your configuration files compatible.
  • Posts: 298
    not really a 'client' is it? openvpn is the actual client. the script is a VPN session manager, yes?
  • Posts: 41
    @martouf
    Take a look at the script, it's clearly a fully featured client that does everything the official one does.
    And no, you cannot do what this script does with only openvpn in any reasonable amount of time.
    So yes, I will call this a client.
    And no I didn't rewrite openvpn for the sake of a bash script, I think the official client must run on top of openvpn too, rewriting massive VPN clients is not one of the brightest ideas, security wise.
  • Posts: 298
    technically speaking, a VPN client is the crypto-and-tunnel bit. the PIA app and your script are session managers. but don't be offended. good session managers make the tool behave nicely.
  • edited November 30 Posts: 6
    I gave your script a try and it is getting hung up on Debian Testing.

    Here is the verbose output. It just stays at "Fetching IP" forever.

    root@debian:~# pia -dvs 30
     [*] US_East latency: 23.604 ms (fast)                    ..
     [*] Connected, OpenVPN is running daemonized on PID 6395                    
     [*] OpenVPN Logs:
         OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Oct 25 2017
         library versions: OpenSSL 1.0.2m 2 Nov 2017, LZO 2.08
         TCP/UDP: Preserving recently used remote address: [AF_INET]208.167.254.210:1197
         UDP link local: (not bound)
         UDP link remote: [AF_INET]208.167.254.210:1197
         WARNING: Failed to stat CRL file, not (re)loading CRL.
         [7d3b9c06a20938301c322a5774f406e1] Peer Connection Initiated with [AF_INET]208.167.254.210:1197
         auth-token received, disabling auth-nocache for the authentication token
         TUN/TAP device tun0 opened
         do_ifconfig, tt->did_ifconfig_ipv6_setup=0
         /sbin/ip link set dev tun0 up mtu 1500
         /sbin/ip addr add dev tun0 local 10.41.10.6 peer 10.41.10.5
         Initialization Sequence Completed
     [>] OpenVPN Settings:
     [*] UDP Protocol.
     [*] 4096 Bit RSA Certificate.
     [*] 256 Bit AES-CBC Cipher.
     [*] SHA256 Authentication.
     [>] Fetching IP...
    
    Post edited by oldfartunix on
  • edited November 30 Posts: 41
    I gave your script a try and it is getting hung up on Debian Testing.

    Here is the verbose output. It just stays at "Fetching IP" forever.

    root@debian:~# pia -dvs 30
     [*] US_East latency: 23.604 ms (fast)                    ..
     [*] Connected, OpenVPN is running daemonized on PID 6395                    
     [*] OpenVPN Logs:
         OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Oct 25 2017
         library versions: OpenSSL 1.0.2m 2 Nov 2017, LZO 2.08
         TCP/UDP: Preserving recently used remote address: [AF_INET]208.167.254.210:1197
         UDP link local: (not bound)
         UDP link remote: [AF_INET]208.167.254.210:1197
         WARNING: Failed to stat CRL file, not (re)loading CRL.
         [7d3b9c06a20938301c322a5774f406e1] Peer Connection Initiated with [AF_INET]208.167.254.210:1197
         auth-token received, disabling auth-nocache for the authentication token
         TUN/TAP device tun0 opened
         do_ifconfig, tt->did_ifconfig_ipv6_setup=0
         /sbin/ip link set dev tun0 up mtu 1500
         /sbin/ip addr add dev tun0 local 10.41.10.6 peer 10.41.10.5
         Initialization Sequence Completed
     [>] OpenVPN Settings:
     [*] UDP Protocol.
     [*] 4096 Bit RSA Certificate.
     [*] 256 Bit AES-CBC Cipher.
     [*] SHA256 Authentication.
     [>] Fetching IP...
    
    Thanks for your feedback @oldfartunix

    Do you have curl installed on your system?
    I have edited the script so if you want to download the new version from github it should check for curl and install if it is missing.
    Also it will give up fetching the IP after two tries so no hang up.
    Thanks again, any other bugs let me know and I will fix asap.
    Post edited by d4rkcat on
  • @d4rkcat

    I do have curl installed.  I installed it after reading the README and before running the makefile. 

    root@debian:~# curl -V
    curl 7.56.1 (x86_64-pc-linux-gnu) libcurl/7.56.1 OpenSSL/1.0.2m zlib/1.2.8 libidn2/2.0.2 libpsl/0.19.1 (+libidn2/2.0.2) libssh2/1.8.0 nghttp2/1.27.0 librtmp/2.3
    Release-Date: 2017-10-23
    Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp 
    Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 

    Also do you know what the 

    WARNING: Failed to stat CRL file, not (re)loading CRL.
    line is referring to in the output?  I tried your script because my normal setup is inexplicably failing using network-manager after 16 months of working.  I'm wondering if it might be related.  Googling it takes me on a deep dive of OpenVPN bugs that is out of my depth.

    Thanks.
  • edited November 30 Posts: 41
    Also do you know what the 

    WARNING: Failed to stat CRL file, not (re)loading CRL.
    line is referring to in the output?  I tried your script because my normal setup is inexplicably failing using network-manager after 16 months of working.  I'm wondering if it might be related.  Googling it takes me on a deep dive of OpenVPN bugs that is out of my depth.

    Thanks.
    @oldfartunix
    That line is an old openvpn bug, it doesn't affect the security of the connection in any way and there is no way to fix it unless they fix it within the openvpn code.
    Seeing as you have curl installed, that means that either your DNS is not answering requests or you cannot curl icanhazip.com for some reason. The ip fetching works every time on my own system, but it is not essential and should not affect the rest of the script, but it is a little strange.

    Try running 
    curl -s -m 4 icanhazip.com  

    from the command line before connecting, it should output your IP address.
    Post edited by d4rkcat on
  • @d4rkcat just wanted to let you know that after uninstalling network-manager and related packages, your script works perfect on Debian Testing.  I like the speed, simplicity and the extra diagnostic output I get in verbose mode.  I'll be sticking with it going forward.  Boring/gory details in my other thread here.

    Nice work!
  • Thanks a lot for this script, I've almost got it working, but when I get to the "Connecting..." step, I get this error in my pia.log:
    UDPv4 link local: [undef]
    UDPv4 link remote: [AF_INET]66.55.144.180:1197
    CRL: cannot read: crl.rsa.4096.pem
    OpenSSL: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
    TLS_ERROR: BIO read tls_read_plaintext error
    TLS Error: TLS object -> incoming plaintext read error
    TLS Error: TLS handshake failed
    SIGUSR1[soft,tls-error] received, process restarting

    I have verified that the file crl.rsa.4096.pem is present in the /etc/openvpn/pia directory, and that root has read permissions:

    -rw-r--r-- 1 root root 1214 Feb  6  2017 crl.rsa.4096.pem

    Been troubleshooting for a while but can't seem to figure it out.  Any help would be greatly appreciated!

  • Posts: 298
    run the script when in the /etc/openvpn/pia directory, or specify the entire path for the file in the script: /etc/openvpn/pia/crl.rsa.4096.pem
  • Posts: 5
    D4rkcat,

    You're damn good, man.  I've been living with archlinux for years and love your script.  I usually insist that everthing I install is done via pacman, but I installed your script the old fashioned way and it works extremely well.  Thank you for making our lives a little bit easier.
  • martouf said:
    run the script when in the /etc/openvpn/pia directory, or specify the entire path for the file in the script: /etc/openvpn/pia/crl.rsa.4096.pem
    Thanks for the suggestions, running the script while in the /etc/openvpn/pia directory resulted in no change, but specifying the full path to the CRL file seems to work.  However, there are two problems with this approach:

    1) The CRL file path is not specified in the script, it is specified in the ovpn configuration file downloaded from PIA.  This means that each file for the individual servers must be modified.
    2) If the script is run with the -u option, these changes are undone, and all the files must be edited again.

    It seems that OpenVPN will not look for the CRL in the same directory as the ovpn file when the path is not specified (which I feel like it should).  Oddly, even adding a ./ in front of the CRL file name didn't work, it had to be the full absolute path.  Even more strange is that OpenVPN seems to have no problem finding the CA file which is also included in the same directory. I looked around to see if there was an environment variable that could be set, and even tried adding /etc/openvpn/pia to my path, but neither of these approaches worked.

    If we could find a way to make this work without having to manually edit every ovpn file, that would be the ideal solution.
  • edited December 8 Posts: 298
    okay, the cwd (current working directory) for openvpn when it gets called isn't /etc/openvpn/pia and it apparently isn't whichever directory you're in when you run the script.

    you don't really need to manually edit all the files:
    (assuming you have rw privileges)

    cd /the/ovpn/file/dir

    for i in $(ls); do
    mv $i $i.orig
    sed 's-crl.rsa.4096.pem-/full/path/to/crl.rsa.4096.pem-' < $i.orig > $i
    done

    ps: it's generally a rule the full path to a config file should always be specified, even if part of it is contained in an environment variable or a string constant like $CONFIGDIR/config.file

    Post edited by martouf on
  • edited December 8 Posts: 38
    EDIT: Reading the previous posts I will wait until a fixed version is issued as from what I can tell it looks like I am having the same issue with directory paths.

    This is exactly what I need (Enter the login only once and select from various connection types).

    Unfortunately the version 0.2 script is not working for me.  I have tried this on two separate laptops, one running Linux Mint 18.2 Mate and the other running Linux Mint 18.2 Cinnamon:

    Downloaded everything and ran:
    ./pia.sh

    I get the following errors after selecting the server to connect to:

     [X] OpenVPN suffered a fatal error. Please review log:                    
    Fri Dec  8 11:04:49 2017 OpenVPN 2.3.10 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on Jun 22 2017
    Fri Dec  8 11:04:49 2017 library versions: OpenSSL 1.0.2g  1 Mar 2016, LZO 2.08
    Fri Dec  8 11:04:49 2017 UDPv4 link local: [undef]
    Fri Dec  8 11:04:49 2017 UDPv4 link remote: [AF_INET]66.55.144.182:1198
    Fri Dec  8 11:04:49 2017 CRL: cannot read: crl.rsa.2048.pem
    Fri Dec  8 11:04:49 2017 TLS_ERROR: BIO read tls_read_plaintext error: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
    Fri Dec  8 11:04:49 2017 TLS Error: TLS object -> incoming plaintext read error
    Fri Dec  8 11:04:49 2017 TLS Error: TLS handshake failed
    Fri Dec  8 11:04:49 2017 SIGUSR1[soft,tls-error] received, process restarting
    Fri Dec  8 11:04:51 2017 UDPv4 link local: [undef]
    Fri Dec  8 11:04:51 2017 UDPv4 link remote: [AF_INET]66.55.144.182:1198
    Fri Dec  8 11:04:51 2017 WARNING: cannot stat file 'pass.txt': No such file or directory (errno=2)
    Fri Dec  8 11:04:51 2017 Error opening 'Auth' auth file: pass.txt: No such file or directory (errno=2)
    Fri Dec  8 11:04:51 2017 Exiting due to fatal error
    
    Post edited by pjc123 on
  • martouf, your last post pointed me in the right direction and I was able to modify your suggestion a little bit and solve my problem.  Thanks very much for your feedback!

    pjc123, the crl issue isn't really a problem with the script, it's an openvpn thing.  I was able to fix this by adding a new function at the top of the script, containing a modified version of martoufs' sed loop.  What worked for me is:
    fixcrl()
    {
        for i in $(ls $VPNPATH); do
            mv $i $i.orig
            sed "s-crl.rsa.4096.pem-$VPNPATH/crl.rsa.4096.pem-g" $i.orig > $i
            rm $i.orig
        done
    }

    Then you just need to call it at the end of the fupdate function, like so:

        fixcrl
        echo -e "\r$INFO Files Updated.                     "

    I later found that the script keeps creating new tunnel interfaces everytime you turn it off and back on, in order to resolve this I added another loop inside of fvpnreset, like so:

        for i in $(lsof -i | grep openvpn | awk '{ print $2 }'); do                                                                                         
            kill -9 $i
        done echo "$INFO VPN Disconnected."

    Finally, I noticed that the permissions on my pass.txt file had somehow been set to 0644 along the way, I just fixed it manually but something you may want to look out for.

    After making these changes, the script now seems to be working just fine, and I'm passing all the leak tests.

    Thanks again to martouf for helping me figure this out, and a big thanks to d4rkcat for writing the original script.  

  • Posts: 298
    the ovpn files are small, and i intended to leave the .orig files around in order to be able to compare them against the PIA-prepared baseline. also, you don't need the trailing 'g' in the sed command. there should only be *one* instance of the pem filename in the input line, and if there's more than one, the 'g' to change them all on the line won't make anything better.
  • Posts: 38
    @hexsorcerer.  Nice, don't know when I will get to try it but this is great.  Now I just need a Windows and Android version!
  • Posts: 38
    @hexsorcerer.  I added your code.  Sometimes I connect, sometimes it doesn't show the list of servers, and other times I get the same error messages as before.
  • Posts: 41
    Hi guys sorry for the delay, been working alot at a new job.
    Looks like some people have a different bash shell that doesn't like
    cd $DIR && do something
    which i thought was pretty standard bash syntax.
    I will edit the script to include full pathnames in the ovpn files but i really don't like that solution and don't see why it needs to be done.
    Give me until 6pm GMT and i will have a new version.
    Cheers
  • edited December 14 Posts: 41
    Think I fixed it, pushed to github.
    Just run pia with a -u to update your ovpn files.
    Also included @hexsorcerer fix to make sure openvpn is killed.
    Let me know if anything else needs fixing.
    Cheers

    EDIT: Also feel free to fork and submit pull requests then fixes can be integrated much easier and that way you get credit :)
    Post edited by d4rkcat on
  • Posts: 298
    if a shell calling itself 'bash' doesn't do
    cmd1 && cmd2

    correctly, then one of these is true:  it isn't really bash (busybox?), bash is broken, or cmd1 isn't playing by the retval rules

    @d4rkcat someone ran into problems because they mounted their fs nosuid .. perhaps there's another mounting nosymfollow ?

  • Posts: 41
    @martouf
    Yes, agreed it's something that works on every linux distro i've ever used and i'm pretty sure all bash shells must do that.
    If you look at line 368 in the commit I pushed today:
    cd $VPNPATH && openvpn --config $CONFIG --daemon
    So you shouldn't need to run the script from $VPNPATH or edit the config files because the subshell should already be running the command from $VPNPATH.
    That line has always been like that and worked well for me on arch, but many of the people who have problems say the problems are path related.
    In any case, my fupdate function has been updated now to edit the ovpn files and add the full paths to all relevant files.
    About running things nosuid; that's never going to work because openvpn and ufw requires root to modify the network stack so I won't be supporting anyone who doesn't run as root.
  • Posts: 38
    Works better, but sometimes when selecting a server number (for example 32 US_East) I get the following message:

    [X] 32 is not valid! 1-0 only.
  • edited December 14 Posts: 41
    @pjc123
    that should not happen, something is going wrong with line 326:
    MAXSERVERS=$(cat $VPNPATH/servers | wc -l)
    can you run from a terminal:
    cat /etc/openvpn/pia/servers | wc -l
    and paste the output?

    What OS are you using?
    Are you running as root?
    Is there anything non-standard about your system?
    Post edited by d4rkcat on
Sign In or Register to comment.