Python - Socket error - python

My code :-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("www.python.org" , 80))
s.sendall(b"GET https://www.python.org HTTP/1.0\n\n")
print(s.recv(4096))
s.close()
Why the output shows me this:-
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Tue, 11 Jul 2017 15:23:55 GMT\r\nVia: 1.1 varnish\r\nConnection: close\r\n\r\n\n\n\nFastly error: unknown domain \n\n\nFastly error: unknown domain: . Please check that this domain has been added to a service.'
How can I fix it?

This is wrong on multiple levels:
to access a HTTPS resource you need to create a TLS connection (i.e. ssl_wrap on top of an existing TCP connection, with proper certificate checking etc) and then send the HTTP request. Of course the TCP connection in this case should go to port 443(https) not 80 (http).
the HTTP request should only contain the path, not the full URL
the line end must be \r\n not \n
you better send a Host header too since many severs require it
And that's only the request. Properly handling the response is a different topic.
I really really recommend to use an existing library like requests. HTTP(S) is considerably more complex as most think who only had a look at a few traffic captures.

import requests
x = requests.get('https://www.python.org')
print x.text
With the requests library, HTTPS requests are very simple! If you're doing this with raw sockets, you have to do a lot more work to negotiate a cipher and etc. Try the above code (python 2.7).
I would also note that, in my experience, Python is excellent for doing things quickly. If you are learning about networking and cryptography, try writing a HTTPS client on your own using sockets. If you want to automate something quickly, use the tools that are available to you. I almost always use requests for this type of task. As an additional note, if you're interested in parsing HTML content, check out the PyQuery library. I've used it to automate interaction with many web services.
Requests
PyQuery

Related

Socket Programming when there is a path

For python
so if you do socket programming u would do a host and port e.g. localhost and 9999 respectively
what if instead of port u have a path e.g. localhost/foo
could u still program a server and client connection without a port number and a path instead e.g. localhost/foo
if not, then would http library work instead so like at the top instead of import socket u type import http and use the thing http library has instead of socket library
is there a way to do it with socket in python when u have a path like localhost/foo but no port i.e. u do not have a host and port like localhost and 9999
Let's take a look at this picture (found here):
Network protocols form a stack where the protocols above rely on the protocols below. For example, when you write a regular letter to your friend, all you care about is to write it in a proper language and write a correct address on the envelope. All the logistics details, whether your letter is delivered by an airplane or a train, or by pigeons - are none of your business, they belong to the lower-level protocol. The post service, in turn, doesn't care about the content of your letter, it just needs to deliver it in time.
A similar thing happens with networking. As you can see on the diagram, HTTP belongs to the highest, Application layer. HTTP services use notions like "URL" or "header", or "content type", but the underlying TCP protocol only cares about delivering the data from one host to another. So, terms like "host" and "port" are from TCP, and terms like "path" are from HTTP.
When you send an HTTP request, for example http://hostname/foo, your host establishes the TCP connection using the host and port information (hostname and 80 is the default port), and then sends the HTTP request over that connection, and that's where path /foo is taken into use.
Now, socket API operates on the transport layer, so it doesn't know anything about paths. You can use socket API to send an HTTP queries, but:
you need to know quite well how HTTP works
it's a lot of manual work
any existing HTTP library uses sockets under the hood
To summarize, you don't really need to deal with sockets for HTTP. Python has modules urllib.request and http.client, but the most popular and easy-to-use Python library for that purpose is requests. With it, sending a request is as simple as:
import requests
response = requests.get('http://localhost/foo')

Are Python.requests safe?

I'm about to use Python.requests to get data from my own online api to my local pc. My api requires authentication which for now is done trough simply posting user/pass:
params = {'user': 'username', 'pass':'password'}
requests.post(url, params=params)
Are this requests safe or is it going to allow a middle-man to capture that user/pass?
P.S My api is using a letsencrypt ssl certificate. Python version 3.7.0
this has nothing to do with the python-requests package, but with the HTTP (and HTTPS) protocols. HTTP is plain-text so anyone that manages to sniff your packets can read the content (hence the username/password pair in clear text). HTTPS uses strong encryption, so even someone sniffing your traffic will have a hard-time deciphering it - no encryption scheme is 100% safe of course but decrypting SSL traffic is currently way too costly even for the NSA.
IOW, what will make your requests "safe" is the use of the HTTPS protocol, not which python (or not python) package you use to write your client code.
Use the HTTPS protocol and it's safe provided you have a valid SSL certificate on your api. If you still feel paranoid/insecure, you can implement end-to-end encryption using an existing algorithm or create your custom algorithm either.

Python SSL Socket Client Authentification

I'm trying to set up a server and client in python where the server authenticates clients using SSL with certificates. There are a lot of examples of SSL certificates online, but everything I've found has the server providing a certificate to the client and the client checking it. I need the server to ensure that the client has the authority to connect to the server. I understand how to generate and send certificates and the basics of how they work. I would type out my code, but my client/server without SSL is working fine and I've been referencing this for SSL. The client/server example at the bottom of that page summarizes my understanding of SSL certs in python.
I realize this isn't much to go on, but if someone could explain the basic modifications to that example to have the server authenticate the client instead of the other way around, that would be awesome. Alternatively, a link to an example or even just some socket methods to investigate would be very helpful. Let me know if more information is needed. I don't mean to be vague and promise I've spent all morning looking for info myself :).
Edit: I'm trying to stick to the basic ssl library. Aka "import ssl".
You would use SSLSocket.getpeercert to get the certificate. The client would need to specify a key and certificate when wrapping the socket just like the server side. On the server side, you will also need to pass ca_certs="path_to_ca_cert_file" and probably also want to specify cert_reqs=CERT_REQUIRED (see. args for ssl.wrap_socket.
In addition to this, it sounds like you might be looking to do certificate based client authentication/authorization? This is a simple matter of using getpeercert to get the client certificate and accessing fields within the certificate to use in a normal authentication path (i.e. Common Name == User Id)
Not really sure what your question refers, however you can see SSL in Python, other resource for SSL in Python, Validating SSL, get SSL Certificate information and you probably found other good links.

Curl-like sending of client certificates without PyCurl: how?

Our client wants a client script that will be installed on their customers' computers to be as trivial to install as possible. This means no extra-install packages, in this case PyCurl.
We need to be able to connect to a website using SSL and expecting a client certificate. Currently this is done calling Curl with os.system() but to get the http return code doing this it looks like we'll have to use the '-v' option to Curl and comb through this output. Not difficult, just a bit icky.
Is there some other way to do this using the standard library that comes with Python 2.6?
I read everything I could find on this and I couldn't see a non-Curl way of doing it.
Thanks in advance for any guidance on this subject whatsoever!
this will do the trick. Note that Verisign don't require a client certificate, it's just a randomly taken HTTPS site.
import httplib
conn = httplib.HTTPSConnection('verisign.com', key_file='./my-key.pem', cert_file='./my-cert.pem')
conn.connect()
conn.request('GET', '/')
conn.set_debuglevel(20)
response = conn.getresponse()
print('HTTP status', response.status)
EDIT: Just for the posterity, Bruno's comment below is a valid one and here's an article how to roll it using the stdlib's socket ssl and socket modules in case it's needed.
EDIT2: Seems I cannot post links - just do a web search for 'Validating SSL server certificate with Python 2.x another day'

Python, implementing proxy support for a socket based application (not urllib2)

I am little stumped: I have a simple messenger client program (pure python, sockets), and I wanted to add proxy support (http/s, socks), however I am a little confused on how to go about it. I am assuming that the connection on the socket level will be done to the proxy server, at which point the headers should contain a CONNECT + destination IP (of the chat server) and authentication, (if proxy requires so), however the rest is a little beyond me. How is the subsequent connection handled, specifically the reading/writing, etc...
Are there any guides on proxy support implementation for socket based (tcp) programming in Python?
Thank you
Maybe use something like SocksiPy which does all the protocol details for you and would let you connect through a SOCKS proxy as you would without it?
It is pretty simple - after you send the HTTP request: CONNECT example.com:1234 HTTP/1.0\r\nHost: example.com:1234\r\n<additional headers incl. authentication>\r\n\r\n, the server responds with HTTP/1.0 200 Connection established\r\n\r\n and then (after the double line ends) you can communicate just as you would communicate with example.com port 1234 without the proxy (as I understand you already have the client-server communication part done).
Have a look at stunnel.
Stunnel can allow you to secure
non-SSL aware daemons and protocols
(like POP, IMAP, LDAP, etc) by having
Stunnel provide the encryption,
requiring no changes to the daemon's
code

Categories