I'm trying to use tor, socksipy and ssl to proxy a ssl connection. My client looks like this:
import socks, ssl
s = socks.socksocket()
s.setproxy(socks.PROXY_TYPE_SOCKS5,"127.0.0.1", 9050)
ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
ssl_sock.connect(('127.0.0.1', 443))
The server just accepts connections and prints getpeername.
The peer name is always 127.0.0.1. It doesn't even matter if I give it a non-valid proxy. The client won't complain, it will connect anyway.
How do I make it connect through the proxy?
I managed to figure it out so I will leave the answer here for future reference.
The first problem was that I tried to connect to 127.0.0.1. As the request was proxied, the proxy would try to connect to 127.0.0.1, so it would try to connect to itself, not to me.
I had to configure my router to forward requests on port 443 to my laptop and then I replaced 127.0.0.1 with my routers IP.
After that was out of the way, I found out that socksipy doesn't play very well with ssl.
I had to call connect on the socket before wrapping it, otherwise I'd get a handshake failure. The code became:
import socks, ssl
s = socks.socksocket()
s.setproxy(socks.PROXY_TYPE_SOCKS5,"127.0.0.1", 9050)
s.connect(('127.0.0.1', 443))
ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
After that, everything was working fine.
Related
I am trying to connect to my HTTPS server via SOCKS4 proxy, but it seems like it is not working.
Here is my code:
headers = "GET / HTTP/1.1\r\nHost: domain.com\r\n\r\n"
import socks
import ssl
conn = socks.socksocket()
conn.set_proxy(socks.SOCKS4, host, port)
conn.connect(("domain.com", 443))
conn = ssl.create_default_context().wrap_socket(conn, server_hostname="domain.com")
conn.send(headers.encode())
After I run that code, I checked my website log and nothing happened. But if I change the connect() port to 80, it worked.
You are connect()'ing the socks TCP connection to the HTTPS server's TLS port before creating the ssl context. Which is fine, however the SSLSocket that wrap_socket() returns will automatically call do_handshake() to negotiate a TLS session only when its connect() method is called, which you are bypassing. So, you will need to manually call do_handshake() after wrap_socket() returns and before calling send(), eg:
headers = "GET / HTTP/1.1\r\nHost: domain.com\r\n\r\n"
import socks
import ssl
conn = socks.socksocket()
conn.set_proxy(socks.SOCKS4, host, port)
conn.connect(("domain.com", 443))
conn = ssl.create_default_context().wrap_socket(conn, server_hostname="domain.com")
conn.do_handshake()
conn.send(headers.encode())
Clients on the same LAN can connect to the server just fine using the server machine's IPv4 address. However, when I have the clients use my router's external ip and port forward down to the server machine, they cannot connect. Any idea, as to why? I created a server and client in GML using the same port forward and it connected just fine using the external ip, so I am assuming I am missing something needed in Python. Here is the stripped down version of the server code:
# Server variables
host = socket.gethostbyname(socket.gethostname())
port = 65000
max_connections = 100
timeout = 5
# Run Server
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))
socket.settimeout(timeout)
socket.listen(max_connections)
run()
I've tried setting the server ip to "" and "0.0.0.0" to no avail. I also tried using the default gateway ip for kicks and giggles. Any advice is appreciated.
I messed up. I thought I had disabled Windows Defender's firewall, but I had only turned off real-time protection. Bah...that's what happens when you're going fast and not paying enough attention. Now it works just fine.
In a simple code like this
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(request)
I have the need of not having the response from the host to arrive. Is that possible? If yes, how can I do that?
I already tried writing
s.close()
but the responses arrive
P.S. the host I connect to is a proxy, if it's useful to say.
so even if the response phisically comes from proxy, in reality it is natively generated by the site (not the proxy, the proxy is the intermediate). so i need to not listen the answer, the response of proxy. Just need to send the request
I'm trying to establish a secure socket connection in Python, and i'm having a hard time with the SSL bit of it. I've found some code examples of how to establish a connection with SSL, but they all involve key files. The server i'm trying to connect with doesn't need to receive any keys or certificates. My question is how do I essentially wrap a python socket connection with SSL. I know for a fact that the cipher i'm suppose to use is ADH-AES256-SHA, and the protocol is TLSv1. This is what i've been trying:
import socket
import ssl
# SET VARIABLES
packet, reply = "<packet>SOME_DATA</packet>", ""
HOST, PORT = 'XX.XX.XX.XX', 4434
# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
# WRAP SOCKET ???
ssl.wrap_socket(sock, ssl_version="TLSv1", ciphers="ADH-AES256-SHA")
# CONNECT AND PRINT REPLY
sock.connect((HOST, PORT))
sock.send(packet)
print sock.recv(1280)
# CLOSE SOCKET CONNECTION
sock.close()
When I run this code, I don't get any errors, but I get a blank response. When trying to debug this code in the command line, by typing in python in the terminal and pasting in code line by line, I get what i'm assuming is a status code when running sock.send(packet). The integer response I get is 26. If anyone knows what this means, or can help in anyway it would be greatly appreciated.
Ok, I figured out what was wrong. It was kind of foolish of me. I had two problems with my code. My first mistake was when specifying the ssl_version I put in TLSv1 when it should have been ssl.PROTOCOL_TLSv1. The second mistake was that I wasn't referencing the wrapped socket, instead I was calling the original socket that I have created. The below code seemed to work for me.
import socket
import ssl
# SET VARIABLES
packet, reply = "<packet>SOME_DATA</packet>", ""
HOST, PORT = 'XX.XX.XX.XX', 4434
# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
# WRAP SOCKET
wrappedSocket = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1, ciphers="ADH-AES256-SHA")
# CONNECT AND PRINT REPLY
wrappedSocket.connect((HOST, PORT))
wrappedSocket.send(packet)
print wrappedSocket.recv(1280)
# CLOSE SOCKET CONNECTION
wrappedSocket.close()
Hope this can help somebody!
You shouldn't be setting PROTOCOL_TLSv1 (or TLSv1). This restricts the connection to TLS v1.0 only. Instead you want PROTOCOL_TLS (or the deprecated PROTOCOL_SSLv23) that supports all versions supported by the library.
You're using an anonymous cipher, because for some reason you think you don't need a certificate or key. This means that there is no authentication of the server and that you're vulnerable to a man in the middle attack. Unless you really know what you're doing, I suggest you don't use anonymous ciphers (like ADH-AES256-SHA).
I was looking for a good working ssl socket that starts the connection with a https package. This helped me a lot but is a little outdated, so here is the code for python3:
import socket
import ssl
package = "GET /ws/LiveWebcastUpdate/22000557 HTTP/1.1\r\nHost:
www.website_name.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64;
rv:80.0) Gecko/20100101 Firefox/80.0\r\nAccept: */*\r\nAccept-Language: nl,en-
US;q=0.7,en;q=0.3\r\nSec-WebSocket-Version: 13\r\nOrigin:
https://www.website_name.com\r\nSec-WebSocket-Key:
NU/EsJMICjSociJ751l0Xw==\r\nConnection: keep-alive, Upgrade\r\nPragma: no-
cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n"
hostname = 'www.website_name.com'
port = 443
context = ssl.create_default_context()
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print(ssock.version())
ssock.send(package.encode())
while True:
data = ssock.recv(2048)
if ( len(data) < 1 ) :
break
print(data)
This is as simple as possible, for more information visit
https://docs.python.org/3/library/ssl.html
There is a lot of fun to be had solving these problems but for me, I found that the underlying infrastructure for python ssl is openssl. Try validating your certificates with openssl and do this before you try to get python to use that same stack.
I needed to import a root certificate into openssl before I could validate the leaf certificate.
This was helpful.
http://gagravarr.org/writing/openssl-certs/others.shtml#ca-openssl
Another interesting thing was that two different build of the same version of python on different hosts had different methods. One had ssl.get_default_verify_paths() and the other didn't had any at all. The lesson here is that python ssl is built on openssl. Different underlying libraries give you a different python.
Python SSL is built on openssl so solve certificate issues in openssl first.
i already have a post which is quite similiar, but i am getting more and more frustrated because it seems nothing is wrong with my network setup. Other software can be seen from the outside (netcat listen servers etc.) but not my scripts.. How can this be??
Note: It works on LAN but not over the internet.
Server:
import socket
host = ''
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print 'Listening..'
conn, addr = s.accept()
print 'is up and running.'
print addr, 'connected.'
s.close()
print 'shut down.'
Client:
import socket
host = '80.xxx.xxx.xxx'
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.close()
Somebody please help me.
Any help is greatly appreciated.
Jake
Edited again to add:
I think you may be missing some basics on socket communication. In order for sockets to work, you need to ensure that the sockets on both your client and server will meet. With your latest revision, your server is now bound to port 63001, but on the local loopback adapter: 127.0.0.1
Computers have multiple network adapters, at least 2: one is the local loopback, which allows you to make network connections to the same machine in a fast, performant manner (for testing, ipc etc), and a network adapter that lets you connect to an actual network. Many computers may have many more adapters (virtual adapters for vlans, wireless vs wired adapters etc), but they will have at least 2.
So in your server application, you need to instruct it to bind the socket to the proper network adapter.
host = ''
port = 63001
bind(host,port)
What this does in python is binds the socket to the loopback adapter (or 127.0.0.1/localhost).
In your client application you have:
host = '80.xxx.xxx.xxx'
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
Now what your client attempts to do is to connect to a socket to port 63001 on 80.xxx.xxx.xxx (which is your wireless internet adapter).
Since your server is listening on your loopback adapter, and your client is trying to connect on your wireless adapter, it's failing, because the two ends don't meet.
So you have two solutions here:
Change the client to connect to localhost by host = 127.0.0.1
Change the server to bind to your internet adapter by changing host = 80.xxx.xxx.xxx
Now the first solution, using localhost, will only work when your server and client are on the same machine. Localhost always points back to itself (hence loopback), no matter what machine you try. So if/when you decide to take your client/server to the internet, you will have to bind to a network adapter that is on the internet.
Edited to add:**
Okay with your latest revision it still won't work because 65535 is the largest post available.
Answer below was to the original revision of the question.
In your code posted, you're listening (bound) on port 63001, but your client application is trying to connect to port 80. Thats why your client can't talk to your server. Your client needs to connect using port 63001 not port 80.
Also, unless you're running an HTTP server (or your python server will handle HTTP requests), you really shouldn't bind to port 80.
In your client code change:
import socket
host = '80.xxx.xxx.xxx'
port = 63001
And in your Server Code:
import socket
host = ''
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), port ))
In your server script you have port = 80, but you don't ever use it. It looks like the server is listening on 63001. And the client is connecting to 80.
If you're going to use 80, make sure you don't have an http server trying to use the port at the same time as well.