Python - Using socket.gethostbyname through proxy - python

I'm using TOR to proxy connections but am having difficulty proxying DNS lookups via socket.gethostbyname("www.yahoo.com") -- I learned that it was not sending DNS traffic via proxy by sniffing traffic with wireshark. Here's a copy of the code I'm using
import StringIO
import socket
import socks # SocksiPy module
import stem.process
from stem.util import term
SOCKS_PORT = 7000
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', SOCKS_PORT)
socket.socket = socks.socksocket
def getaddrinfo(*args):
return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
socket.getaddrinfo = getaddrinfo
socket.gethostbyname("www.yahoo.com") <--- This line is not sending traffic via proxy
Any help is greatly appreciated!

You're calling gethostbyname in the socket module. It doesn't know anything about your SOCKS socket; it is simply interacting with your operating system's name resolution mechanisms. Setting socket.socket = socks.socksocket may affect network connections made through the socket module, but the module does not make direct connections to DNS servers to perform name resolution so replacing socket.socket has no impact on this behavior.
If you simply call the connect(...) method on a socks.socksocket object using a hostname, the proxy will perform name resolution via SOCKS:
s = socks.socksocket()
s.connect(('www.yahoo.com', 80))
If you actually want to perform raw DNS queries over your SOCKS connection, you'll need to find a Python DNS module to which you can provide your socksocket object.

If you resolve the DNS yourself with Socks5 you may leak information about your own computer. Instead try tunneling with Proxifier, then to Tor. Alternatively you can use SocksiPy's Socks4A extension. This will make sure information is not leaked.

Related

Python Sending UDP packets through HTTP/SOCKS proxy

I tried to send UDP packet from proxy but proxy is not working. Why?
import socket, sys, random, socks, os
ip = sys.argv[1]
port = int(sys.argv[2])
proxy = random.choice(open("proxy.txt").readlines()).split(':')
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.connect((str(proxy[0]), int(proxy[1])))
bytes = random._urandom(100)
sock.sendto(bytes,(ip,port))
You cannot send UDP through a HTTP proxy. You cannot send UDP through a SOCKS4 proxy either. With SOCKS5 the proxy might support it or not but in any case you have to speak the proxy protocol for this - which you don't.
Currently you only do import socks but this does not magically provide proxy support. Instead you either have to use socks.setdefaultproxy to set the proxy for all sockets or socks.socksocket with s.set_proxy to get a socket which supports proxying. See the documentation for the details.

Python Requests, how to specify port for outgoing traffic?

I'm working on a project where we want to assign a whitelist packet filters for incoming traffic on a firewall and we are using python script with requests library to make some https requests to some servers outside of that network. For now the script is using ephemeral ports to connect to the servers, but we would like to make these https requests through specific ports. This would allow us to create strict whitelist for these ports.
How can I specify the port to the requests library through which the request should be sent? Script is currently using the following type of code to send the necessary requests.
response = requests.post(data[0], data=query, headers=headers, timeout=10)
This works, but I would now need to specify the port through which the http post request should be sent to allow for more strict packet filtering on the network. How could this port declaration be achieved? I have searched for solution to this from several sources already and came up with absolutely nothing.
requests is built on urllib3, which offers the ability to set a source address for connections; when you set the source address to ('', port_number) you tell it to use the default host name but pick a specific port.
You can set these options on the pool manager, and you tell requests to use a different pool manager by creating a new transport adapter:
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
class SourcePortAdapter(HTTPAdapter):
""""Transport adapter" that allows us to set the source port."""
def __init__(self, port, *args, **kwargs):
self._source_port = port
super(SourcePortAdapter, self).__init__(*args, **kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(
num_pools=connections, maxsize=maxsize,
block=block, source_address=('', self._source_port))
Use this adapter in a session object, the following mounts the adapter for all HTTP and HTTPS connections, using 54321 as the source port:
s = requests.Session()
s.mount('http://', SourcePortAdapter(54321))
s.mount('https://', SourcePortAdapter(54321))
You can only set the one source port, limiting you to one active connection at a time. If you need to rotate between ports, register multiple adapters (one per URL) or re-register the catch-all mounts each time.
See the create_connection() utility function documentation for the details on the source_address option:
If source_address is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default.

How python handle DNS resolution with Tor Relay?

Supposing this working code :
import win_inet_pton
import socks
import socket
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "localhost", 9050)
s.connect(("xmh57jrzrnw6insl.onion",80))
s.send("GET / HTTP/1.1\r\n\r\n")
print 'sended'
data=s.recv(1024)
print data
Tor service is indeed running at port 9050.
In normal condition, python will perform DNS resolution through the SOCKS5 proxy, which is connected to the Tor relay. However, Tor do not handle UDP packet(It handles the resolution directly from the hostname in the TCP packet) so DNS resolution will fail.
How is it possible that this code work? (the equivalent code in java for exemple will fail as the DNS resolution can't be made).
IT is explained in this link: Python requests fails when tryign to connect to .onion site
You simply have to use socks5h instead of socks5

Python - Toggling a connection to my local SOCKS proxy

I am writing a crawler in Python that will run through Tor. I have Tor working and used code from this YouTube tutorial on how to route my Python requests to go through the Tor SOCKS proxy at 127.0.0.1:9050.
What I can't figure out is how to toggle this on/off within my script. Some requests I want to go through Tor and some I don't. Basically, I can't figure out the correct "close" or "shutdown" method in the socket objects I am using because I don't understand them.
Here's what happens now
import socket
import socks
import requests
def connect_to_socks():
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9050, True)
socket.socket = socks.socksocket
r = requests.get('http://wtfismyip.com/text')
print r.text #prints my ordinary IP address
connect_to_socks()
r = requests.get('http://wtfismyip.com/text')
print r.text #prints my Tor IP address
How do I turn off the socket routing to the SOCKS proxy so that it goes through my ordinary internet connection?
I'm hoping to use requests instead of urllib2 as it seems a lot easier but if I have to get into the guts of urllib2 or even httplib I will. But would prefer not to.
Figured it out by listening to this good YouTube tutorial.
Just need to call socket.setdefaultproxy() and it brings me back.
For Python 3 you can set back default socket by using this:
socks.setdefaultproxy(None)
socket.socket = socks.socksocket

How to get python gspread to use a SOCKS proxy server for connections?

How could I get my script that's using gspread to have the gspread connections to google's servers use a SOCKS proxy?
SocksiPy should work for this, as per the SO question: How can I use a SOCKS 4/5 proxy with urllib2?.
import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 8080)
socket.socket = socks.socksocket
import gspread
# do whatever
If this is not the desired result, you may have to create a custom instance of the bundled HTTPSession object.

Categories