3

Below is the simple script I'm using to redirect regular HTTP requests on port 8080, it redirects(causes them to be at least) them depending on the source IP address right away.

It works (for HTTP), however I would like to have the same behavior for HTTPS requests coming over 443 port. Assume that if the redirection was not present, incoming clients to this simple server would be able to handshake with the target they are being redirected to via a self signed certificate.

import SimpleHTTPServer
import SocketServer

LISTEN_PORT = 8080
source = "127.0.0.1"
target = "http://target/"

class simpleHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_POST(self):
        clientAddressString = ''.join(str(self.clientAddress))

        if source in clientAddressString:
            # redirect incoming request
            self.send_response(301)
            new_path = '%s%s' % (target, self.path)
            self.send_header('Location', new_path)
            self.end_headers()

handler = SocketServer.TCPServer(("", LISTEN_PORT), simpleHandler)
handler.serve_forever()

I can use a self signed certificate and have access to files "server.crt" and "server.key" that are normally used for this connection(without the middle redirecting python server). I am not sure what happens when I put a redirection in between like this, although I assume it has to be part of the hand-shaking chain.

How can I achieve this behavior?

Is there anything I should modify apart from the new target and the response code within request headers?

Kerem
  • 2,867
  • 24
  • 35

1 Answers1

3

I will split my answer into Networking and Python parts.

On the Networking side, you cannot redirect at the SSL layer - hence you need a full HTTPs server, and redirect the GET/POST request once the SSL handshake is complete. The response code, and the actual do_POST or do_GET implementation would be exactly the same for both HTTP and HTTPs.

As a side note, don't you get any issues with redirecting POSTs? When you do a 301 on POST, the browser will not resend the POST data to your new target, so something is likely to break at the application level.

On the Python side, you can augment an HTTP server to an HTTPs one by wrapping the socket:

import BaseHTTPServer, SimpleHTTPServer
import ssl

handler = BaseHTTPServer.HTTPServer(("", LISTEN_PORT), simpleHandler)
handler.socket = ssl.wrap_socket (handler.socket, certfile='path/to/combined/PKCS12/container', server_side=True)
handler.serve_forever()

Hope this helps.

RomanK
  • 1,258
  • 7
  • 18
  • I was not aware that the request data was not being redirected along. In that case I think it would make more sense to make a new request using the contents of the one you want to redirect. Or does any of the *HTTPServer modules have that kind of ability? Thank you for the heads up. – Kerem Mar 15 '15 at 16:12
  • It's more at the HTTP level - irrespective of Python or *HTTPServer classes. When you issue a 302 or 301 response, you provide a Location. The browser does not resubmit the same POST data to the same location. If the client is controlled by you, then of course you can write client-side code to submit automatically. – RomanK Mar 15 '15 at 17:30
  • I think 307 response is used to preserve the request method - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307 – Aditya Nov 11 '21 at 09:38