Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop external deps #2 (Review) #226

Merged
merged 17 commits into from
May 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ A python3 script (systemd service as well) to manage openvpn connections. Create
- Now list and connect to servers with "Netflix" --netflix, "Peer To Peer" --p2p, "Dedicated IP" --dedicated, \\
"Tor Over VPN" --tor, "Double VPN" --double, "Anti DDos" --anti-ddos support.
- Desktop notification are shown when VPN connects and disconnects. (needs to run without sudo)
- Auto retry if [soft,auth-failure] received, auto failover to next best server if connection dies.
- Auto retry if \[soft,auth-failure\] received, auto failover to next best server if connection dies.
- NVRAM write support for Asuswrt-merlin
- Pass through openvpn options, e.g. openpyn uk -o '--status /var/log/status.log --log /var/log/log.log'
- Logs stored in '/var/log/openpyn/' for information and troubleshooting.
- Logs stored in '~/.local/share/openpyn/logs/' for information and troubleshooting.
- Temporarily disable ipv6 to prevent leakage (when using -f).

## Demo
Expand All @@ -38,7 +38,7 @@ A python3 script (systemd service as well) to manage openvpn connections. Create

```bash
# common dependencies
sudo apt install openvpn unzip wget python3-setuptools python3-pip
sudo apt install openvpn python3-setuptools python3-pip
```

2. The following python dependencies are needed and will be installed when using pip.
Expand Down Expand Up @@ -77,22 +77,22 @@ For the latest in development features, try the 'test' branch instead
xcode-select --install
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
echo 'export PATH="/usr/local/sbin:$PATH"' >> ~/.bash_profile
brew install python3 wget openvpn
brew install python3 openvpn
sudo brew services start openvpn
```

```bash
git clone https://github.com/jotyGill/openpyn-nordvpn.git
cd openpyn-nordvpn
git pull
sudo pip3 install --upgrade .
python3 -m pip install --upgrade .
```

4. On Asuswrt-merlin, install [Entware-ng-3x](https://gist.github.com/1951FDG/3cada1211df8a59a95a8a71db6310299#file-asuswrt-merlin-md) (credit: [1951FDG](https://github.com/1951FDG))

```bash
# common dependencies
opkg install git git-http iputils-ping procps-ng-pgrep python3 python3-pip sudo unzip wget
opkg install git git-http iputils-ping procps-ng-pgrep python3 python3-pip sudo
```

```bash
Expand Down
10 changes: 7 additions & 3 deletions openpyn/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import sys
import os.path
import subprocess

import sys

__version__ = "2.7.6.dev1"
__license__ = "GNU General Public License v3 or later (GPLv3+)"
__data_files__ = []
__basefilepath__ = os.path.dirname(os.path.abspath(__file__)) + "/"

log_format = "%(asctime)s [%(levelname)s] %(message)s"
log_folder = "/var/log/openpyn" # logs will be saved here

_xdg_data_home = os.environ.get('XDG_DATA_HOME')
if not _xdg_data_home:
_xdg_data_home = os.path.join(os.environ.get('HOME'), '.local', 'share')
ovpn_folder = os.path.join(_xdg_data_home, 'openpyn', 'files')
log_folder = os.path.join(_xdg_data_home, 'openpyn', 'logs') # logs will be saved here


if sys.platform == "linux":
Expand Down
9 changes: 4 additions & 5 deletions openpyn/asus.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import subprocess

import verboselogs
from openpyn import __basefilepath__, api
from openpyn import __basefilepath__, api, ovpn_folder
from openpyn.converter import T_CLIENT, Converter

verboselogs.install()
Expand All @@ -12,7 +12,6 @@
def run(server, c_code, client, rgw=None, comp=None, adns=None, tcp=False, test=False, debug=False):
with open(__basefilepath__ + "credentials", 'r') as f:
lines = f.read().splitlines()
f.close()

url = "https://api.nordvpn.com/server"
json_response = api.get_json(url)
Expand All @@ -24,12 +23,12 @@ def run(server, c_code, client, rgw=None, comp=None, adns=None, tcp=False, test=
port = "udp"
port_name = "1194"
protocol_name = "udp"
folder = "ovpn_udp/"
folder = "/ovpn_udp/"
if tcp:
port = "tcp"
port_name = "443"
protocol_name = "tcp-client"
folder = "ovpn_tcp/"
folder = "/ovpn_tcp/"

vpn_config_file = server + ".nordvpn.com." + port + ".ovpn"

Expand All @@ -41,7 +40,7 @@ def run(server, c_code, client, rgw=None, comp=None, adns=None, tcp=False, test=
c.set_protocol(protocol_name)

c.set_name(server)
c.set_source_folder(__basefilepath__ + "files/" + folder)
c.set_source_folder(ovpn_folder + folder)
c.set_certs_folder("/jffs/openvpn/")

c.set_accept_dns_configuration(adns)
Expand Down
9 changes: 4 additions & 5 deletions openpyn/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ def extract_information(self, input_file):
self._extract_tls_control_channel_security(line)
continue
data = data + line
lines.close()

# print(data, end="")

Expand Down Expand Up @@ -349,7 +348,7 @@ def _extract_log_verbosity(self, line):
def _extract_custom_configuration(self, line):
"""Specific extractor for Custom Configuration"""
value = line.strip()
# These are already added by OpenVPN
# these are already added by OpenVPN
if value == "tun-mtu 1500":
pass
elif value == "tun-mtu-extra 0":
Expand All @@ -358,7 +357,7 @@ def _extract_custom_configuration(self, line):
pass
elif value == "mssfix 1450":
pass
# These are already added by ASUSWRT-Merlin
# these are already added by ASUSWRT-Merlin
elif value == "client":
pass
elif value == "nobind":
Expand All @@ -367,10 +366,10 @@ def _extract_custom_configuration(self, line):
pass
elif value == "persist-tun":
pass
# Pull is implied by "client"
# 'pull' is implied by "client"
elif value == "pull":
pass
# These are already added by us
# these are already added by us
elif value.startswith("auth-user-pass"):
pass
elif value.startswith("comp-lzo"):
Expand Down
34 changes: 14 additions & 20 deletions openpyn/credentials.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import getpass
import logging
import os
import subprocess
import sys

import verboselogs
from openpyn import __basefilepath__, root
from openpyn import __basefilepath__

verboselogs.install()
logger = logging.getLogger(__package__)
Expand All @@ -21,23 +20,18 @@ def save_credentials() -> None:
if not sys.__stdin__.isatty():
raise RuntimeError("Please run %s in interactive mode" % __name__)

if root.verify_running_as_root() is False:
raise RuntimeError("Please run as 'sudo openpyn --init' the first time. \
Root access is needed to store credentials in '%s'." % credentials_file_path)
else:
logger.info("Storing credentials in '%s' with openvpn \
logger.info("Storing credentials in '%s' with openvpn \
compatible 'auth-user-pass' file format", credentials_file_path)

username = input("Enter your username for NordVPN, i.e [email protected]: ")
password = getpass.getpass("Enter the password for NordVPN: ")
try:
with open(credentials_file_path, 'w') as creds:
creds.write(username + "\n")
creds.write(password + "\n")
creds.close()
# Change file permission to 600
subprocess.check_call(["sudo", "chmod", "600", credentials_file_path])

logger.info("Awesome, the credentials have been saved in '%s'", credentials_file_path)
except (IOError, OSError):
raise RuntimeError("IOError while creating 'credentials' file.")
username = input("Enter your username for NordVPN, i.e [email protected]: ")
password = getpass.getpass("Enter the password for NordVPN: ")
try:
with open(credentials_file_path, 'w') as creds:
creds.write(username + "\n")
creds.write(password + "\n")
# change file permission to 600
os.chmod(credentials_file_path, 0o600)

logger.info("Awesome, the credentials have been saved in '%s'", credentials_file_path)
except (IOError, OSError):
raise RuntimeError("IOError while creating 'credentials' file.")
5 changes: 3 additions & 2 deletions openpyn/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def filter_by_load(server_list: List, max_load: int, top_servers: int) -> List:
for server in server_list:
server_load = int(server[1])
# skip if server_load < 4, sometimes they don't work
if server_load < max_load and len(remaining_servers) < top_servers and server_load > 3:
remaining_servers.append(server)
if max_load >= server_load > 3:
if len(remaining_servers) < top_servers:
remaining_servers.append(server)
return remaining_servers
12 changes: 6 additions & 6 deletions openpyn/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ def apply_dns_rules():
def apply_fw_rules(interfaces_details: List, vpn_server_ip: str, skip_dns_patch: bool) -> None:
root.verify_root_access("Root access needed to modify 'iptables' rules")

# Empty the INPUT and OUTPUT chain of any current rules
# empty the INPUT and OUTPUT chain of any current rules
subprocess.check_call(["sudo", "iptables", "-F", "OUTPUT"])
subprocess.check_call(["sudo", "iptables", "-F", "INPUT"])

apply_dns_rules()
logger.notice("Temporarily disabling ipv6 to prevent leakage")
manage_ipv6(disable=True)

# Allow all traffic out over the vpn tunnel
# allow all traffic out over the VPN tunnel
# except for DNS, which is handled by systemd-resolved script
# NOTE: that def helped with leaky DNS queries, nothing in wireshark too
# weird that ping ya.ru was showing "operation not permitted"
Expand Down Expand Up @@ -148,24 +148,24 @@ def apply_fw_rules(interfaces_details: List, vpn_server_ip: str, skip_dns_patch:
"-j", "ACCEPT"
])

# Allow loopback traffic
# allow loopback traffic
subprocess.check_call("sudo iptables -A INPUT -i lo -j ACCEPT".split())
subprocess.check_call("sudo iptables -A OUTPUT -o lo -j ACCEPT".split())

# best practice, stops spoofing
subprocess.check_call("sudo iptables -A INPUT -s 127.0.0.0/8 -j DROP".split())

# Default action if no other rules match
# default action if no other rules match
subprocess.check_call("sudo iptables -P OUTPUT DROP".split())
subprocess.check_call("sudo iptables -P INPUT DROP".split())


# open specified ports for devices in the local network
# Open specified ports for devices in the local network
def internally_allow_ports(interfaces_details: List, internally_allowed: List) -> None:
for interface in interfaces_details:
# if interface is active with an IP in it, and not "tun*"
if len(interface) == 3 and "tun" not in interface[0]:
# Allow the specified ports on internal network
# allow the specified ports on internal network
for port in internally_allowed:
subprocess.call([
"sudo", "iptables",
Expand Down
16 changes: 8 additions & 8 deletions openpyn/management/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ def show(do_notify) -> bool:
break

try:
# Create the notification object and show once
# create the notification object and show once
summary = "Openpyn"
body = "Initiating connection (If stuck here, try again)"
if detected_os == "linux":
if do_notify:
notification = Notify.Notification.new(summary, body)
notification.show()
logger.warning("{} {}".format(summary, body))
logger.warning("%s %s", summary, body)
elif detected_os == "darwin":
if do_notify:
notification = "\"{}\" with title \"{}\"".format(body, summary)
Expand All @@ -89,9 +89,9 @@ def show(do_notify) -> bool:
if detected_os == "linux":
if do_notify:
notification.update(summary, body)
# Show again
# show again
notification.show()
logger.info("{} {}".format(summary, body))
logger.info("%s %s", summary, body)
elif detected_os == "darwin":
if do_notify:
notification = "\"{}\" with title \"{}\"".format(body, summary)
Expand All @@ -108,7 +108,7 @@ def show(do_notify) -> bool:
if do_notify:
notification.update(summary, body)
notification.show()
logger.info("{} {}".format(summary, body))
logger.info("%s %s", summary, body)
elif detected_os == "darwin":
if do_notify:
notification = "\"{}\" with title \"{}\"".format(body, summary)
Expand All @@ -120,7 +120,7 @@ def show(do_notify) -> bool:

except KeyboardInterrupt:
body = "Disconnected, Bye."
logger.info("{} {}".format(summary, body))
logger.info("%s %s", summary, body)
if detected_os == "linux":
if do_notify:
notification.update(summary, body)
Expand All @@ -131,7 +131,7 @@ def show(do_notify) -> bool:
os.system("""osascript -e 'display notification {}'""".format(notification))
except ConnectionResetError:
body = "Disconnected, Bye. (ConnectionReset)"
logger.info("{} {}".format(summary, body))
logger.info("%s %s", summary, body)
if detected_os == "linux":
if do_notify:
notification.update(summary, body)
Expand All @@ -148,7 +148,7 @@ def show(do_notify) -> bool:
def parse_args(argv: List[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Management interface for openpyn to display notifications and log"
"them to /var/log/openpyn/openpyn-notifications.log ", allow_abbrev=False)
"them to {}/openpyn-notifications.log".format(log_folder), allow_abbrev=False)
parser.add_argument(
'--do-notify', dest='do_notify', help='try to display desktop notifications.',
action='store_true')
Expand Down
Loading