Coder Social home page Coder Social logo

nordvpn-proxy's Introduction

nordvpn-proxy

lint dockerfile

build multi-arch images

Docker Size Docker Pulls Docker Stars ImageLayers

This is a NordVPN client docker container using openvpn that use the recommended NordVPN servers, and opens a SOCKS5 (dante server) and http proxy (tinyproxy).

VPN servers selection is performed through nordnvpn API.(country, technology, protocol)

Added docker image version for raspberry.

Whenever the connection is lost the unbound, tinyproxy and sock daemons are killed, disconnecting all active connections (tunnel down event).

What is this?

This image is largely based on jeroenslot/nordvpn-proxy with dante free socks server added. you can then expose port 1080 from the container to access the VPN connection via the SOCKS5 proxy.

To sum up, this container:

  • Opens the best connection to NordVPN using openvpn and the conf downloaded using NordVpn API according to your criteria.
  • Starts a HTTP proxy that route eth0:8888 to eth0:1080 (socks server) with tinyproxy
  • Starts a SOCKS5 proxy that routes eth0:1080 to tun0/nordlynx with dante-server.
  • Starts unbound as dnssec querying specified DNS.

The main advantage is that you get the best recommendation for each selection.

Usage

Script for OpenVpn config download is base on the one developped for haugene 's docker transmission openvpn https://haugene.github.io/docker-transmission-openvpn/provider-specific/

The container is expecting three parameters to select the vpn server:

NOTE: This container works best using the p2p technology.

NOTE: At the moment, this container has no kill switch... meaning that when the VPN connection is down, the connection will be rerouted through your provider. although, on tunnel down event, the socks server is stopped preventing to relay unprotected requests, and defaults route through eth0 (not vpn) are deleted.

NOTE: as of 22/03/28, NORDVPN_LOGIN and NORDVPN_PASS secrets file are replaced with a single file, NORDVPN_CREDS, having login at first line and password as the second line.

  • DNS to uses external DNS, if none given: "1.1.1.1@853#cloudflare-dns.com 1.0.0.1@853#cloudflare-dns.com"
  • NORDVPN_USER=email or service user
  • NORDVPN_PASS=pass or service pass
  • EXIT_WHEN_IP_NOTEXPECTED=(0|1) # stop container when detected network is not as expected (based on /24 networks)
  • NORDVPN_SERVER=<#>.nordvpn.com: eg: nl568.nordvpn.com, get configuration based on server's fqdn, bypassing all api's recommendations. Connection may fail when the server is offline or overloaded. has precedence over NORDVPN_COUNTRY and NORDVPN_CATEGORY.
  • NORDVPN_TESTS=[1-4], simple tests to test basic api filtering functions.
  • WRITE_OVPN_STATUS=(0|1): write openvpn status (CONNECTED/NOTCONNECTED) to /var/tmp/ovpn_status. you may mount the file to get the openvpn status outside the container.
  • WAITSEC=30, default value, time to wait between two vpn login.

How to run the container

  • Just copy/paste the grey text block starting with version 3.8. to a file named docker-compose.yml
  • Set values for NORDVPN_TECHNOLOGY, NORDVPN_PROTOCOL, NORDVPN_COUNTRY
  • adapt if needed LOCAL_NETWORK, TZ
  • create file nordvpn_creds containing your login in the first line and your password in the second line.

nordvpn_creds:

thisismyusername
thisismypassword

Nordvpn openvpn credentials are to be found following that procedure:

  • Go to NordVPN website and log in

  • Under accounts - Services - click NordVPN

  • Click - Set up NordVPN manually - at the bottom right of the page.

  • You will receive a verification code in your email that you use for NordVPN services. Type the code in the popup window the preceded the email check.

  • Copy the credentials using the โ€œCopyโ€ buttons on the right for your new encrypted user name and password and paste them in nordvpn_creds

  • start the container: docker compose up -d

once the container is started, you will see in the logs these two lines, indicating that both socks and http proxies are up.

nordvpn-proxy  | INFO: OPENVPN: up: starting tinyproxy
.....
nordvpn-proxy  | ok: run: tinyproxy: (pid 103) 1s, normally down

```yaml
version: '3.8'
services:
  proxy:
    image: edgd1er/nordvpn-proxy:latest
    restart: unless-stopped
    ports:
      - "1081:1080" # socks port udp or tcp
      - "8888:8888/tcp" # http proxy tcp.
#    devices:
#      - /dev/net/tun #Optional, will be created if not preset
    sysctls:
      - net.ipv4.conf.all.rp_filter=2
    cap_add:
      - NET_ADMIN
    environment:
      - TZ=America/Chicago
      - DNS=1.1.1.1@853#cloudflare-dns.com 1.0.0.1@853#cloudflare-dns.com
#      - NORDVPN_USER=<email>
#      - NORDVPN_PASS='<pass>'
      - NORDVPN_COUNTRY=germany #Optional, by default, servers in user's country.
      - NORDVPN_PROTOCOL=udp #Optional, udp by default, udp or tcp
      - NORDVPN_CATEGORY=p2p #Optional, Africa_The_Middle_East_And_India, Asia_Pacific, Europe, Onion_Over_VPN, P2P, Standard_VPN_Servers, The_Americas
      - NORDVPN_LOGIN=<email> #Not required if using secrets
      - NORDVPN_PASS=<pass> #Not required if using secrets
      - OPENVPN_PARAMETERS= #optional, empty by default, overrides openvpn config file with parameters
      - OPENVPN_LOGLEVEL= #Optional, define openvpn verbose level 0-9
      - EXIT_WHEN_IP_NOTASEXPECTED=0 # when detected ip is not belonging to remote vpn network
      - LOCAL_NETWORK=192.168.0.0/24 # allow network access for socks and tinyproxy.
      - TINYPORT=8888 #define tinyport inside the container, optional, 8888 by default,
      - TINY_LOGLEVEL=Error #Critical (least verbose), Error, Warning, Notice, Connect (to log connections without Info's noise), Info
      - DANTE_LOGLEVEL="error" #Optional, error by default, available values: connect disconnect error data
      - DANTE_ERRORLOG=/dev/stdout #Optional, /dev/null by default
      - CRON_LOGLEVEL=9 #optional, from 0 to 9, 8 default, 9 quiet.
      - DEBUG=0 #(0/1) activate debug mode for scripts, dante, nginx, tinproxy
    secrets:
        - NORDVPN_CREDS
    volumes:
      - ./myconfig/:/config/

secrets:
    NORDVPN_CREDS:
        file: ./nordvpn_creds

Healthcheck

script checks for:

  • proper dnssec resolution
  • openvpn service being up
  • openvpn being connected
  • warns if openvpn remote ip seems not coherent

if any of these fail, services are restarted.

dockerfile healtcheck:

  • use NORDVPN api to validate protection
if test $( curl -m 10 -s https://api.nordvpn.com/vpn/check/full | jq -r '.["status"]' ) = "Protected" ; then exit 0; else exit 1; fi 

Kill switch

When vpn interface (tun) is up, default route through unprotected interface (eth0) is removed.

To ensure that little or no traffic is forwarded unprotected, services are stopped on any of these events:

  • when the api returns that the status is not protected, the container stops.(every 5min)
  • when openvpn returns a status NOTCONNECTED, all services are stopped, openvpn is restarted. when ok, dante and tinyproxy are started.(checked every 5 minutes)
  • when openvpn service is stopped, the down phase (runit feature) stops all other services.
  • when the tun interface is disconnected, openvpn fires the down.sh script, stopping all services.

Other image

Another image is available using nordvpn's client. Openvpn and wireguard (nordlynx) protocols are available. better speed may be achieved with wireguard.

names links
nordlynx-proxy image: https://hub.docker.com/r/edgd1er/nordlynx-proxy
nordlynx-proxy github: https://github.com/edgd1er/nordlynx-proxy

nordvpn-proxy's People

Contributors

catwith1hat avatar dependabot[bot] avatar edgd1er avatar fraxker avatar twitchax avatar xanderphillips avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nordvpn-proxy's Issues

OpenVPN deprecated cipher option warning

Seeing the following in OpenVPN logs:

DEPRECATED OPTION: --cipher set to 'AES-256-CBC' but missing in --data-ciphers (AES-256-GCM:AES-128-GCM). Future OpenVPN version will ignore --cipher for cipher negotiations. Add 'AES-256-CBC' to --data-ciphers or change --cipher 'AES-256-CBC' to --data-ciphers-fallback 'AES-256-CBC' to silence this warning

AUTH: Received control message: AUTH_FAILED

I've created a nordvpn_creds file with the Nordvpn credentials although the readme says to create two files with the login and pass.. the instructions for me are a bit confusing.

nordvpn_creds containing:

nordvpn_login=******
nordvpn_pass=*****

log:

proxy-1 | 2024-01-21 11:01:20: OVPN: CREATING TUN INTERFACE /DEV/NET/TUN:
proxy-1 | 2024-01-21 11:01:20: INFO: NORDVPN: Using cached values for json_countries
proxy-1 | 2024-01-21 11:01:20: INFO: NORDVPN: Using cached values for json_groups
proxy-1 | 2024-01-21 11:01:20: INFO: NORDVPN: Using cached values for json_technologies
proxy-1 | 2024-01-21 11:01:20: INFO: Checking curl installation
proxy-1 | 2024-01-21 11:01:20: INFO: DNS: resolution ok
proxy-1 | 2024-01-21 11:01:21: INFO: OVPN: ok, configurations download site reachable
proxy-1 | 2024-01-21 11:01:21: INFO: NORDVPN: Removing existing configs in /config
proxy-1 | 2024-01-21 11:01:21: INFO: Checking NORDPVN API responses
proxy-1 | 2024-01-21 11:01:21: INFO: Selecting the best server...
proxy-1 | 2024-01-21 11:01:21: INFO: NORDVPN: Searching for country : xxxxxxxx (153)
proxy-1 | 2024-01-21 11:01:21: INFO: NORDVPN, searching for group: legacy_p2p
proxy-1 | 2024-01-21 11:01:21: INFO: NORDVPN: searching for technology: openvpn_udp
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: Best server : xxxx.nordvpn.com, load: 9
proxy-1 | 2024-01-21 11:01:32: INFO: NORDVPN: selected: xxxx.nordvpn.com, VPN_PROVIDER_HOME: /config
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: Downloading config: xxxx.nordvpn.com.ovpn
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: Downloading from: https://downloads.nordcdn.com/configs/files/ovpn_udp/servers/xxxx.nordvpn.com.udp.ovpn
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: ########################################################
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: Files found: 1
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: config: /config/xxxx.nordvpn.com.ovpn
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: openvpn log level: 0
proxy-1 | 2024-01-21 11:01:32: INFO: OVPN: ########################################################
proxy-1 | 2024-01-21 11:01:32: OVPN: FOUND EXISTING OPENVPN CREDENTIALS AT /CONFIG/OPENVPN-CREDENTIALS.TXT:
proxy-1 | 2024-01-21 11:01:32: OVPN: SETTING OPENVPN CREDENTIALS...:
proxy-1 | 2024-01-21 11:01:32: OVPN: LOCAL_NETWORK: 192.168.6.0/24, GATEWAY: 172.19.0.1, DEVICE ETH0:
proxy-1 | adding route to local network 192.168.6.0/24 via 172.19.0.1 dev eth0
proxy-1 | 2024-01-21 11:01:32 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
proxy-1 | 2024-01-21 11:01:32 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
proxy-1 | 2024-01-21 11:01:33 AUTH: Received control message: AUTH_FAILED
proxy-1 | 2024-01-21 11:01:33: OVPN: VPN CONNECTION LOST, STOPPING UNBOUND:
proxy-1 | 2024-01-21 11:01:33: OVPN: WAITING 30 SECONDS BEFORE RESTARTING:

Verified correct credentials parsed from ENV, container fails to AUTH. Logs show an error ./run: line 73: }: too many arguments

Steps to reproduce: set up nordvpn with password containing spaces.
(Similar password with no spaces does not throw the error in the run script from line 73)

ALSO: Even without spaces in password getting AUTH error using same username and password as works in official nordvpn client.

INFO: OVPN: Creating tun interface /dev/net/tun
INFO: OVPN: Checking curl installation
INFO: OVPN: DNS resolution ok
INFO: OVPN: ok, configurations download site reachable
INFO: OVPN: Removing existing configs in /etc/service/openvpn/nordvpn
INFO: Checking NORDPVN API responses
INFO: OVPN:Selecting the best server...
INFO: WARNING: OVPN: empty or invalid NORDVPN_COUNTRY (value=). Ignoring this parameter. Possible values are:AL,AR,AU,AT,BE,BA,BR,BG,CA,CL,CO,CR,HR,CY,CZ,DK,EE,FI,FR,GE,DE,GR,HK,HU,IS,ID,IE,IL,IT,JP,LV,LT,LU,MY,MX,MD,NL,NZ,MK,NO,PL,PT,RO,RS,SG,SK,SI,ZA,KR,ES,SE,CH,TW,TH,TR,UA,AE,GB,US,VN, or Albania,Argentina,Australia,Austria,Belgium,Bosnia and Herzegovina,Brazil,Bulgaria,Canada,Chile,Colombia,Costa Rica,Croatia,Cyprus,Czech Republic,Denmark,Estonia,Finland,France,Georgia,Germany,Greece,Hong Kong,Hungary,Iceland,Indonesia,Ireland,Israel,Italy,Japan,Latvia,Lithuania,Luxembourg,Malaysia,Mexico,Moldova,Netherlands,New Zealand,North Macedonia,Norway,Poland,Portugal,Romania,Serbia,Singapore,Slovakia,Slovenia,South Africa,South Korea,Spain,Sweden,Switzerland,Taiwan,Thailand,Turkey,Ukraine,United Arab Emirates,United Kingdom,United States,Vietnam,. Please check https://haugene.github.io/docker-transmission-openvpn/provider-specific/#nordvpn
INFO: OVPN: Searching for group: legacy_p2p
INFO: OVPN:Searching for technology: openvpn_tcp
INFO: OVPN: Best server : us6308.nordvpn.com, load: 17
INFO: OVPN: Downloading config: us6308.nordvpn.com.ovpn
INFO: OVPN: Downloading from: https://downloads.nordcdn.com/configs/files/ovpn_udp/servers/us6308.nordvpn.com.udp.ovpn
selected: us6308.nordvpn.com, VPN_PROVIDER_HOME: /etc/service/openvpn/nordvpn
INFO: OVPN: ########################################################
INFO: OVPN: Files found: 1
INFO: OVPN: config: /etc/service/openvpn/nordvpn/us6308.nordvpn.com.ovpn
INFO: OVPN: openvpn log level: 0
INFO: OVPN: ########################################################
./run: line 73: [: too many arguments
INFO: OVPN: Found existing OPENVPN credentials at /config/openvpn-credentials.txt
INFO: OVPN: Setting OpenVPN credentials...
2023-11-17 04:11:29 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
2023-11-17 04:11:29 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
2023-11-17 04:11:36 AUTH: Received control message: AUTH_FAILED
INFO: OVPN: VPN connection lost, stopping unbound
INFO: OVPN: Waiting 30 seconds before restarting

sockd closes all fds on startup and that pegs the process at 100% CPU for several minutes

In this code block, Dante naively closes all file descriptors when it forks. For some reason, this loop iterates over an excessively large number of descriptors with recent kernels or docker versions. When starting dante inside Docker, the process pegs at 100% and when strace-ing I get:

close(39136061)                         = -1 EBADF (Bad file descriptor)
close(39136062)                         = -1 EBADF (Bad file descriptor)
close(39136063)                         = -1 EBADF (Bad file descriptor)
close(39136064)                         = -1 EBADF (Bad file descriptor)
close(39136065)                         = -1 EBADF (Bad file descriptor)
close(39136066)                         = -1 EBADF (Bad file descriptor)

After about 10 minutes and wasting CPU cycles, it somehow manages to iterate the whole file descriptor domain.

A workaround is to set a reasonable nofile ulimit for the service. I think that Dante should close to the new close_range syscall.

I will submit a PR to fix this, but I want a bug to link to.

route: ioctl 0x890b failed: File exists

route add default dev eth0 is failing with this error.

This is the output of the route command inside the container.

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         *               0.0.0.0         U     0      0        0 eth0

default         192.168.16.1    0.0.0.0         UG    0      0        0 eth0
192.168.16.0    *               255.255.240.0   U     0      0        0 eth0

If this is the way it's supposed to look like at this point of the script execution, make it ignore "route: ioctl 0x890b failed: File exists" errors and continue.

Replacing route add default dev eth0 with ip route replace default dev eth0 might be a solution.

Edit: It failing is possibly a symptom, not the cause of the issue. So using 'replace' is probably only a partial fix.

Thanks again.

PS: after restarting the service many times it eventually work. very weird since I always use docker-compose down to start clean.
PPS: I'm still debugging to find out why this happens.

nordvpn-proxy     | INFO: OVPN: DNS resolution ok
nordvpn-proxy     | INFO: OVPN: ok, configurations download site reachable
nordvpn-proxy     | INFO: OVPN: Removing existing configs in /etc/service/openvpn/nordvpn
nordvpn-proxy     | INFO: ########################################################
nordvpn-proxy     | INFO: openvpn: stopping
nordvpn-proxy     | INFO: openvpn: stopped
nordvpn-proxy     | INFO: OVPN: Checking curl installation
nordvpn-proxy     | INFO: ########################################################
nordvpn-proxy     | INFO: openvpn: stopping
nordvpn-proxy     | route: ioctl 0x890b failed: File exists
nordvpn-proxy     | INFO: OVPN: Checking curl installation
nordvpn-proxy     | INFO: ########################################################
nordvpn-proxy     | INFO: openvpn: stopping
nordvpn-proxy     | route: ioctl 0x890b failed: File exists
nordvpn-proxy     | INFO: OVPN: Checking curl installation

Sometimes I also get:

nordvpn-proxy     | INFO: OVPN: DNS resolution ok
nordvpn-proxy     | ping: bad address 'downloads.nordcdn.com'

Please make the installation instructions

It would be really cool if you did a guide on how to install this for Windows / Linux Docker compose. Personally, I'm not familiar with docker at all, it's unrealistic to find a video demonstrating how to deploy such a solution to YouTube.
P.S. Still can't get it to install.

NORDVPN_CREDS?

Usually docker secrets contain one information (i.e. username or password), not multiple.

With your latest commit f99564d you just introduced a breaking change removing NORDVPN_LOGIN and NORDVPN_PASS replacing it with NORDVPN_CREDS. Unfortunately I can't roll back a version using docker hub as a registry since there aren't any tags.

I can't find any example for the NORDVPN_CREDS secrets file. Should it just be login & password newline delimited?

EDIT: just checked the commit and you are doing

   NORDVPN_LOGIN=$(cat /run/secrets/NORDVPN_CREDS| head -1)
    NORDVPN_PASS=$(cat /run/secrets/NORDVPN_CREDS| tail -1)

I mean, I can create a NORDVPN_CREDS file just like that, but I actually was happy with LOGIN & PASS. Why the change? Why this crude method of doing head and tail on the file? I liked it better before ๐Ÿ˜‰

Save status of VPN to a file

I could really use a file that says wheter vpn is working as intended or not.
One way to do it would be to add it to check_openvpn() on healthcheck.sh. Something like: Save 1 to a file if it's working and 0 if it's not.
This way I could mount that file on my system and access the vpn status from my other scripts.

Ideally it should only write to this file if there's an environment variable enabling this feature. So that the people that don't need it won't have unnecessary writes to their drives.

Thanks, anyway. :)

PS: I know there is an EXIT_WHEN_IP_NOTEXPECTED option. But for my use-case I need it disabled.

Need NORDVPN_SERVER

Hello, can you add option configure NORDVPN_SERVER? (now only NORDVPN_COUNTRY)

./run: line 61: NORDVPN_LOGIN: unbound variable

Hello,

Thanks for the great work! unfortunately even if i follow the instruction that are on the docker hub portal, i still have an issue when i run the container:

./run: line 61: NORDVPN_LOGIN: unbound variable

I have tried to debug and found that the variable is used inside the run script instead of NORDVPN_USER.

This is the command line that I refer to:

docker run -it --rm --cap-add NET_ADMIN -p 1080:1080 -e NORDVPN_USER= -e NORDVPN_PASS='' -e NORDVPN_COUNTRY=Poland
-e NORDVPN_PROTOCOL=udp -e NORDVPN_CATEGORY=p2p edgd1er/nordvpn-proxy

Suggestions:

  • Setting the NORDVPN_LOGIN at the creation of the container instead of NORDVPN_USER and changing the documentation on the Docker hub repository
  • Replacing all the occurence of NORDVPN_LOGIN with NORDVPN_USER

Maybe some other solutions exist but those are the most straight forward :-)

Thanks

Best Regards,
Jerome

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.