I was wondering how to use NordVPN servers to change IP address during my web automation with Python.
Let's say to use it with mechanize this way:
br.open("url", proxies="nordvpn proxy")
Thanks in advance.
I know this might be a bit late, but recently I encountered a challenge similar to your question.
Generally, I am using python to execute Nord's Linux commands.
import subprocess
import time
import subprocess, re, random, datetime
# Nordvpn shinanigance skip to line 105
def getCountries():
"""
This function will return a list of the current countries with available servers for your nordvpn account.
"""
nord_output = subprocess.Popen(["nordvpn", "countries"], stdout=subprocess.PIPE)
countries = re.split("[\t \n]", nord_output.communicate()[0].decode("utf-8"))
while "" in countries:
countries.remove("")
return countries
def chooseRandom(country_list):
"""
This function will randomly choose a country out of the available countries list.
"""
return country_list[random.randrange(0, len(country_list))]
def logIn(random_country):
"""
This function will take the randomly chosen country and attempt to log in to NordVPN using that country.
"""
print("{} has been selected as the random country.".format(random_country))
# subprocess.call(["nordvpn", "c", random_country])
cmd = ["nordvpn", "c", random_country]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
o, e = proc.communicate()
if "Whoops! We couldn't connect you" in o.decode('ascii'):
print("not connected. Retrying...")
logIn(chooseRandom(getCountries()))
else:
print("Connected to {}".format(random_country))
def checkConnection():
print("checkConnection connection!")
cmd = ['nordvpn', 'c']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
o, e = proc.communicate()
if "Connected" in o.decode('ascii'):
return True
else:
return False
def tryConnection():
print("Trying connection!")
cmd = ['nordvpn', 'c']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
time.sleep(2)
if checkConnection() == True:
print("Sucessfull Connection with:\n" + email +" " +password)
else:
print("Failed")
cmd = ['nordvpn', 'logout']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("Logged out")
def loginWithPassword(email, password):
cmd = ['nordvpn', 'login', '--username', email, '--password', password]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# print(proc)
o, e = proc.communicate()
stdout = proc.communicate()[0]
# print (format(stdout))
if "is not correct" in o.decode('ascii'):
print("Wrong password")
if "already logged in" in o.decode('ascii'):
print("Already logged in")
nord_output = subprocess.Popen(["nordvpn", "status"], stdout=subprocess.PIPE)
status = re.split("[\r \n :]", nord_output.communicate()[0].decode("utf-8"))[-2]
if status == "Disconnected":
print("Disconnected from nord!")
logIn(chooseRandom(getCountries()))
else:
print("Connected...")
print("Calling diconnecting to randomize...")
subprocess.call(["nordvpn", "disconnect"])
logIn(chooseRandom(getCountries()))
So, you just have to call
loginWithPassword("email", "password")
Massive thanks to this guy whom I borrowed a few things from
NordVPN_Randomizer
Here is a simple way to do it using Python plus Command Line (if you are using Windows):
import os
current = os.getcwd() #get working directory
os.chdir("C:\\Program Files\\NordVPN") #cd into nord directory
os.system("nordvpn -c -g 'United States'") #change ip
os.chdir(current) #cd back into working directory
Related
I am trying to create a program using PyQt5, ADB, scrcpy, and python. When I click on connect, which starts a scrcpy server and mirrors the android device on the screen, my UI freezes until I close my scrcpy session/server. I will share both .py file codes that are used to make this work and look.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import uic
import os
import sys
from ADBee import *
from twt_start import *
devs = devices()
log_window = []
# GET LIST OF CONNECTED SERIAL NUMBERS
os.chdir('resources/ui/')
class TB_Main_Window(QMainWindow):
def __init__(self):
super(TB_Main_Window, self).__init__()
uic.loadUi('main.ui', self)
self.find_button.clicked.connect(lambda: self.find_devices(devs))
self.connect_button.clicked.connect(self.connect_to_device)
self.disconnect_button.clicked.connect(self.disconnect_from_device)
self.connect_button.setEnabled(False)
self.disconnect_button.setEnabled(False)
#make = self.device_make.placeholderText.connect(self.get_selected_items)
self.show()
def find_devices(self, devs):
count = 0
try:
if len(devs) == 0:
print(" --- No Devices Found --- \n")
elif len(devs) > 0:
for d in devs:
self.device_listbox.addItem(devs[count])
count += 1
self.connect_button.setEnabled(True)
except:
print("\nCould Not Find Devices\n")
def get_selected_items(self):
serial = self.device_listbox.currentText()
print(serial)
return serial
# CONNECT TO SELECTED DEVICE (SERIAL)
def connect_to_device(self):
_serial = self.device_listbox.currentText()
self.find_button.setEnabled(False)
self.connect_button.setEnabled(False)
num_devices = self.device_listbox.count()
if num_devices == 1:
try:
twt()
except:
print("\nCould Not Connect To Device\n")
if num_devices > 1:
try:
self.find_button.setEnabled(False)
self.connect_button.setEnabled(False)
twt_ws(serial=_serial)
except:
print(f'Failed to connect to:{_serial}')
elif num_devices == 0:
print(f'\nNo Devices Found\n')
def disconnect_from_device(self):
self.device_listbox.setEnabled(True)
self.find_button.setEnabled(True)
self.connect_button.setEnabled(False)
try:
kill_server()
print(f"Device Disconnect Successfully")
except:
print(f"Can't Disconnect From Device")
app = QApplication([])
window = TB_Main_Window()
window.show()
sys.exit(app.exec_())
############################################################################################
from subprocess import Popen as send
import subprocess
import os
def twt(window_title='Twitedb3rn', width='480', height='900'):
try:
orientation()
console_send = send(
f"scrcpy --always-on-top --window-title={window_title} --window-width={width} --window-height={height} ",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_twt, errors = console_send.communicate()
print(f'\n\tTWT Started\n\n!---START---!\n\n{_twt}\n!---END---!')
console_send.wait()
except:
print(f'\nScrcpy Failed {errors}\n\n')
def twt_ws(window_title='Twitedb3rn', width='480', height='900', serial='99031FFBA0083T'):
try:
orientation_ws(serial)
new_directoy = os.chdir('resources/scrcpy')
console_send = send(
f'scrcpy --always-on-top --window-title={window_title} --window-width={width} --window-height={height} -s{serial}',
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_twt_ws, errors = console_send.communicate()
console_send.wait()
print(f'\n\tTWT Started\n\n!---START---!\n\n{_twt_ws}\n!---END---!')
except:
print(f'\nTWT Failed\n\n')
print(errors)
#adb shell dumpsys window | grep 'mLandscapeRotation'
def orientation_ws(serial):
try:
console_send = send(
f"adb -s {serial} shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Rotation Disabled')
try:
home = send(f'adb -s {serial} shell input keyevent KEYCODE_HOME')
home.communicate()
home.wait()
console_send = send(
f"adb -s {serial} shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:1",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Set Landscape')
except:
print(f'\nScreen Landscape Failed')
print(errors)
except:
print(f'\nScreen Rotation Not Disabled')
print(errors)
return errors
def orientation():
try:
console_send = send(
f"adb shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Rotation Disabled')
try:
home = send(f'adb shell input keyevent KEYCODE_HOME')
home.communicate()
home.wait()
console_send = send(
f"adb shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:0",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
_orientation, errors = console_send.communicate()
console_send.wait()
print(f'\nScreen Set Porttrait')
except:
print(f'\nScreen Portrait Failed')
print(errors)
except:
print(f'\nScreen Portrait Not Disabled')
print(errors)
return errors
All in all, it looks like your adb communication code is better formulated as something like the below.
Note I've elided all try/excepts; it's better to handle exceptions and errors "higher up" rather than just print out an error and let the program continue as if nothing bad had happened.
import subprocess
def set_adb_value(name, value):
# TODO: this is not safe against shell injection vulnerabilities if `name` and `value`
# are user-controlled.
subprocess.check_call(
f"adb shell content insert --uri content://settings/system "
f"--bind name:s:{name} "
f"--bind value:{value}"
)
def set_orientation(landscape=False):
# Disable screen rotation
set_adb_value("accelerometer_rotation", "i:0")
# Press home key
subprocess.check_call("adb shell input keyevent KEYCODE_HOME")
# Set rotation
set_adb_value("user_rotation", ("i:1" if landscape else "i:0"))
def start_scrcpy(window_title="Twitedb3rn", width="480", height="900", landscape=False):
set_orientation(landscape=landscape)
# TODO: this is not safe against shell injection vulnerabilities.
return subprocess.Popen(
f"scrcpy --always-on-top "
f"--window-title={window_title} "
f"--window-width={width} "
f"--window-height={height}",
)
No, you will need to understand what you're doing with your subprocesses first, and then use communicate etc. accordingly.
Many of those Popen (or send) uses you have right now would be better served by subprocess.check_call(), by the way.
This was the answer.
I removed:
_twt, errors = console_send.communicate()
console_send.wait()
and also:
_twt_ws, errors = console_send.communicate()
console_send.wait()
The following script (which should take the output from p1 and pipe it to p2, and then output the result in the terminal) doesn't seem to work as expected.
Code as follows :
#!/binr/bin/python
# Script to lauch mosquitto_sub to monitor a mqtt topic -- SYNTAX : mosk topic
import sys
import subprocess
total = len(sys.argv)
cmdargs = str(sys.argv)
print ("The total numbers of args passed to the script: %d " % total)
print ("Args list: %s " % cmdargs)
# Pharsing args one by one
print ("Script name: %s" % str(sys.argv[0]))
print ("First argument: %s" % str(sys.argv[1]))
path = str(sys.argv[1])
print (path)
p1 = subprocess.Popen(['mosquitto_sub','-h','192.168.1.100','-t',path,'-v'], shell=False, stdout=subprocess.PIPE)
p2 = subprocess.Popen(['ts'], stdin=p1.stdout, shell=False, stdout=subprocess.PIPE)
for line in p2.stdout:
sys.stdout.write(line)
with an input as follows "./mosk2.py test/+" and whilst publishing MQTT via mosquitto on the relevant topics, I never get the expected output in the terminal
Solved - I ended up stepping neatly around the problem (cheating) as follows :
cmd = "mosquitto_sub -h 192.168.1.100 -v -t " + topic + " | ts"
print "The command which was executed is : " , cmd
def run_command(command):
process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
print output.strip()
rc = process.poll()
return rc
run_command(cmd) #This is the lauch of the actual command
this is the function i am creating, i have one argument that can tell to print real time or not since some of the process take like an hour. and since i am subprocesing several at the same time, another argument to raise an error and stop everything, or just let the main script run.
but if i do print_real_time True, i loose the p.communicate()
i could store all the prints from the iter in a variable and return that, but how do i put in order the std out, and the stderr, and get the return value to see if did fail or not?
def launch_subprocess_cmd(command_to_lunch, cwd=None, print_real_time=False, raise_errors=True):
"""
for a given command line will lunch that as a subprocess
:param command_to_lunch: string
:param print_real_time: boolean
:param cwd: the folder path from where the command should be run.
:param raise_errors: boolean if the return code of the subprocess is different than 0 raise an error an stop all scripts.
else the main script will keep running and can access the third return value of this function and decide what to do with it.
:return: list com return the stdout and the stderr of the Popen subprocess.
"""
if cwd is None:
p = subprocess.Popen(command_to_lunch, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
else:
p = subprocess.Popen(command_to_lunch, cwd=cwd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
if print_real_time is True:
for i in iter(p.stdout.readline, b''):
print i
com = p.communicate()
if raise_errors is True:
if p.returncode != 0:
raise ValueError("\n\nSubprocess fail: \n" + "Error captures: \n" + "stdout:\n" + com[0] + "\nstderr:\n" + com[1] + "\n")
# com[0] is std_out, com[1] is std_err and p.return code is if the subprocess was successful or not with a int number
return com[0], com[1], p.returncode
thanks guys =)
A possible solution to your problem is to store the stdout stream in a list when print_real_time is True and then use the content of the list to generate the stdout data string. If print_real_time is not True, then use the content from com[0] instead.
def launch_subprocess_cmd(cmd, cwd=None, print_real_time=False, raise_errors=True):
"""
for a given command line will lunch that as a subprocess
:param cmd: string
:param print_real_time: boolean
:param cwd: the folder path from where the command should be run.
:param raise_errors: boolean if the return code of the subprocess is different
than 0 raise an error an stop all scripts else
the main script will keep running and can access the third
return value of this function and decide what to do with it.
:return: list com return the stdout and the stderr of the Popen subprocess.
"""
if cwd is None:
p = subprocess.Popen(cmd, stderr=subprocess.PIPE,
stdout=subprocess.PIPE, shell=True)
else:
p = subprocess.Popen(cmd, cwd=cwd, stderr=subprocess.PIPE,
stdout=subprocess.PIPE, shell=True)
stdout_list = []
if print_real_time is True:
for i in iter(p.stdout.readline, b''):
stdout_list.append(i)
print i
com = p.communicate()
stdout_data = "".join(stdout_list) if print_real_time is True else com[0]
if raise_errors is True:
if p.returncode != 0:
raise ValueError("\n\nSubprocess fail: \n" + "Error captures: \n" +
"stdout:\n" + stdout_data + "\nstderr:\n" +
com[1] + "\n")
# stdout_data is stdout, com[1] is stderr and
# p.return code is if the subprocess was successful or not with a int number
return stdout_data, com[1], p.returncode
As a side note, I would also urge you to try to rewrite the program to not use shell=True in your Popen calls. It may require that you preprocess the input cmd into a list of base command and arguments, but it is generally considered a bad idea to use shell=True.
launch_subprocess_cmd(command_to_lunch, cwd=None, print_real_time=False, raise_errors=True):
if cwd is None:
p = subprocess.Popen(command_to_lunch, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
else:
p = subprocess.Popen(command_to_lunch, cwd=cwd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
stdout_list = []
errout_list = []
if print_real_time is True:
for i in iter(p.stdout.readline, b''):
stdout_list.append(i)
print i
for j in iter(p.stderr.readline, b''):
errout_list.append(j)
print j
com = p.communicate()
if print_real_time is True:
stdout_data = "".join(stdout_list)
std_err_data = "".join(errout_list)
else:
stdout_data = com[0]
std_err_data = com[1]
if raise_errors is True:
if p.returncode != 0:
raise ValueError("\n\npopen fail:\n" + command_to_lunch + "\nError:\n" + "Error captures:\n" + "stdout:\n" + stdout_data + "\nstderr:\n" + std_err_data + "\n")
# com[0] is out, com[1] is errors and p.return code is if it fail or not
return stdout_data, std_err_data, p.returncode
This is my code:
def uploadByRSync(host, user, passwd, src, dst, statusManager):
try:
os.environ["RSYNC_PASSWORD"] = passwd
print host, user, passwd, src, dst
parameters = ["rsync", "-azP", "--partial", src ,"{3}#{0}::{2}/{1}".format(host, dst, user, user)]
print " ".join(parameters)
process = subprocess.Popen(parameters, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
for line in unbuffered(process):
if "%" in line:
spl = line.split()
statusManager.uploadSpeed = spl[2]
statusManager.uploaded = spl[1]
return not process.wait()
except Exception as ex:
print ex
return False
newlines = ['\n', '\r\n', '\r']
def unbuffered(proc, stream='stdout'):
stream = getattr(proc, stream)
with contextlib.closing(stream):
while True:
out = []
last = stream.read(1)
# Don't loop forever
if last == '' and proc.poll() is not None:
break
while last not in newlines:
# Don't loop forever
if last == '' and proc.poll() is not None:
break
out.append(last)
last = stream.read(1)
out = ''.join(out)
print out
yield out
When running with the py2app version I can never get an output. When running as script everything works just fine. ps: this code runs on a separated thread of a Qt app. Does anyone have any idea why this is happening?
Most likely you have a stream buffering issue. Here is how you can output all lines of your process in real time:
import subprocess
import select
p = subprocess.Popen(parameters,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0)
poll = [p.stdout.fileno(), p.stderr.fileno()]
while True:
# check if process is still running and read remaining data
if p.poll() is not None:
for l in p.stdout.readlines():
print(l)
for l in p.stderr.readlines():
print(l)
break
# blocks until data is being recieved
ret = select.select(poll, [], [])
for fd in ret[0]:
line = p.stdout.readline() if fd == p.stdout.fileno() else p.stderr.readline()
print(line)
Just made a test changing the Popen call by a simple 'ls',but I still cannot get the output when running py2app version. It works just fine when running python script. When I kill the py2app version app the output is just printed.
process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
I am trying to execute the following code, which asks me password for each and every ssh command though I provide my password in the code. Can any one please tell me where I am doing mistake. Thanks in advance
import signal
from subprocess import call, PIPE, Popen
from time import sleep
import os, pty
class SshCmd:
socket = ''
pid = 0
password = None
def __init__(self, password = None):
if password:
SshCmd.password = password
# start agent
devnull = open(os.devnull, 'w')
call(['killall', 'ssh-agent'], stderr=devnull)
process = Popen('/usr/bin/ssh-agent', stdout=PIPE, stderr=devnull)
stdout, stderr = process.communicate()
lines = stdout.splitlines()
SshCmd.socket = lines[0].decode().split(';')[0].split('=')[1]
SshCmd.pid = lines[1].decode().split(';')[0].split('=')[1]
devnull.close()
# unlock key
pid, fd = pty.fork()
if 0 == pid:
# child adds key
os.execve('/usr/bin/ssh-add', ['/usr/bin/ssh-add'], \
{'SSH_AUTH_SOCK': SshCmd.socket, 'SSH_AGENT_PID': SshCmd.pid})
else:
# parent send credentials
cmsg = os.read(fd, 1024)
os.write(fd, SshCmd.password.encode())
os.write(fd, os.linesep.encode())
cmsg = os.read(fd, 1024)
if len(cmsg) <= 2:
os.waitpid(pid, 0)
else:
os.kill(pid, signal.SIGTERM)
def execve(self, path, args, env = {}):
if not SshCmd.password:
return
pid = os.fork()
if 0 == pid:
env['SSH_AUTH_SOCK'] = SshCmd.socket
env['SSH_AGENT_PID'] = SshCmd.pid
os.execve(path, args, env)
else:
os.waitpid(pid, 0)
def ssh(self, user, host, cmd, args = []):
cmdLine = cmd
for arg in args:
cmdLine += ' '
cmdLine += arg
self.execve('/usr/bin/ssh',
['/usr/bin/ssh',
'-o',
'UserKnownHostsFile=/dev/null',
'-o',
'StrictHostKeyChecking=false',
'%(user)s#%(host)s' % {'user': user, 'host': host},
cmdLine])
if '__main__' == __name__:
other = SshCmd('passowrd')
other.ssh('root', 'host', '/sbin/ifconfig')
other.ssh('root', 'host', 'ping', ['-c', '5', 'localhost'])
You are not making a mistake. In order to skip the password step, you need to pre-validate your request, you can do this by using the command ssh-copy-id first. which will store the credentials and allow connection through a key. You need to have a key first, which you can create with ssh-keygen
Note: these commands may change depending on the linux distribution.