I have a python Flask application that serves a website and does a bunch of other things such as querying a database, displaying the results on the website...and also creating an instance of the Tor process. A website that returns the current IP is visited and this is printed 5 times, where a new request for clean circuits is sent via Signal.NEWNYM on each of the loops.
All this happens in Debian. I am logged as admin, and when I run the APP on the command line (python app.py), inside the python virtual environment, everything goes well: each loop prints the IP, waits for new IP, prints the IP...5 times.
However, I am trying to serve this website with UWSGI and NGINX. When the APP gets loaded using UWSGI, everything else seems to be fine, but when I request a new IP using Signal.NEWNYM the requests hangs. If I have harakiri set on the UWSGI config, it will kill the worker after the set time. If not, the requests will hang forever.
Any clue what the issue could be? Permissions? If so, what files/directories? The sockets? I just don't understand how it works perfectly when it runs on the command line the request hangs using UWSGI.
This is some of the code, for context:
def get_tor_session():
session = requests.session()
session.proxies['https'] = 'socks5://localhost:9050'
session.proxies['http'] = 'socks5://localhost:9050'
return session
def renew_connection():
print("Renewing connection")
torControl.signal(Signal.NEWNYM)
time.sleep(torControl.get_newnym_wait())
def startTor(config):
GEOIPFILE_PATH = "/usr/share/tor/geoip"
try:
urllib.request.urlretrieve('https://raw.githubusercontent.com/torproject/tor/main/src/config/geoip', GEOIPFILE_PATH)
print ("GeoIP file updated")
except Exception as e:
print ('[INFO] Unable to update geoip file. Using local copy.', e)
try:
# start tor
print("Starting tor")
torProcess = launch_tor_with_config(
config=config, # use our custom config
tor_cmd='tor', # start tor normally
completion_percent=100, # blocks until tor is 100%
timeout=90, # wait 90 sec for tor to start
take_ownership=True # subprocess will close with parent
)
# connect a controller
print("Connecting controller")
torControl = Controller.from_port(
address="127.0.0.1", port=int(config['ControlPort']))
# auth controller
torControl.authenticate(password='somepass')
print("Connected to tor process")
return torProcess, torControl
except Exception as e:
print(e)```
config = {
'ClientOnly': '1',
'ControlPort': '9051',
'DataDirectory': '/tmp/tor',
'GeoIPFile': '/usr/share/tor/geoip',
'EntryNodes': '{UK}',
'ExitNodes': '{UK}',
'HashedControlPassword':'16:489A6B09FB6D0E9D601D22CFCF438DB9832E7584450E4AF1F0709FF8FB'}
torProcess, torControl = startTor(config)
Then I call a function where I have a loop that prints the IP address and renews it.
for i in range(5):
session = get_tor_session()
print(f"trying: {i}")
print(session.get('http://icanhazip.com/', timeout=5).text)
renew_connection()
This is the NGINX conf
log_format timedlog '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent $upstream_response_time '
'"$http_referer" "$http_user_agent"';
server {
listen 80;
server_name somewebsite;
return 301 somewebsite
}
server {
listen 443 default ssl;
ssl_certificate /etc/letsencrypt/live/myweb/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myweb/privkey.pem;
server_name somewebsite;
access_log /var/log/nginx/myweb-access.log timedlog;
error_log /var/log/nginx/myweb-error.log;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/myweb.sock;
}
}
And the UWSGI ini file
[uwsgi]
plugins = python3
pythonpath = /home/admin/myweb/venv/bin
module = wsgi
socket = /tmp/myweb.sock
chmod-socket = 775
chdir = /home/admin/myweb
master = true
module = app:app
uid = www-data
gid = www-data
processes = 1
threads = 1
harakiri = 60
python-autoreload = 0
touch-reload = /tmp/myweb.touchme