Building a web proxy using Flask and Python offers a simple yet effective way to implement secure browsing. A web proxy serves as an intermediary between a user and the internet, providing privacy and security by masking the user’s IP address and encrypting data. Flask, a micro web framework for Python, allows us to quickly set up a lightweight web server for this purpose. This guide walks through the technical steps to build a basic web proxy with Flask, providing an overview of the necessary components, including the handling of HTTP requests, response filtering, and security measures.
Prerequisites
Before starting, make sure you have the following installed on your system:
- Python 3.x
- Flask web framework
- Requests library for handling HTTP requests
- HTML and CSS knowledge for customization
Setting Up Your Python Environment
To begin, ensure that Flask and the Requests library are installed in your Python environment. You can install them using pip:
pip install Flask requests
After installing these dependencies, you’re ready to proceed with the web proxy setup.
Creating the Flask Web Proxy
Now, let’s start building the proxy. Below is a basic example of how to handle HTTP requests and responses.
python
import requests
from flask import Flask, request, Response
app = Flask(__name__)
@app.route(‘/’, methods=[‘GET’])
def proxy():
url = request.args.get(‘url’)
if not url:
return “Error: No URL provided”, 400
try:
# Send request to the target URL
response = requests.get(url)
# Extract content and headers from the original response
headers = response.headers
content = response.content
# Return the response content and headers to the client
return Response(content, headers=headers, status=response.status_code)
if __name__ == ‘__main__’:
app.run(debug=True)
In this example:
We set up a simple route / to handle GET requests.
The url parameter is fetched from the query string.
The requests.get() function makes an HTTP request to the target URL, and the response content is returned to the client.
Handling Different HTTP Methods
A real-world proxy needs to handle multiple HTTP methods such as POST, PUT, DELETE, etc. Here’s how you can extend the basic proxy to handle these methods:
python
@app.route(‘/’, methods=[‘POST’, ‘GET’, ‘PUT’, ‘DELETE’])
def proxy_all():
url = request.args.get(‘url’)
if not url:
return “Error: No URL provided”, 400
try:
if request.method == ‘GET’:
response = requests.get(url)
elif request.method == ‘POST’:
response = requests.post(url, data=request.form)
elif request.method == ‘PUT’:
response = requests.put(url, data=request.form)
elif request.method == ‘DELETE’:
response = requests.delete(url)
headers = response.headers
content = response.content
return Response(content, headers=headers, status=response.status_code)
except requests.RequestException as e:
return f”Error: {e}”, 500
This code ensures that the proxy will forward requests made with different HTTP methods to the target URL and return the appropriate response.
Implementing SSL for Secure Browsing
For secure browsing, it’s crucial that your proxy server operates over HTTPS. Flask’s built-in server does not support HTTPS directly, so you need to implement SSL manually.
To add SSL support, you’ll need to generate an SSL certificate. You can generate a self-signed certificate using the following OpenSSL command:
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.crt
After generating the certificate and key files, modify the Flask application to use SSL:
python
if __name__ == ‘__main__’:
app.run(debug=True, ssl_context=(‘server.crt’, ‘server.key’))
This ensures that your proxy server will encrypt communication between clients and the server using HTTPS.
Response Content Filtering
A useful feature for a proxy server is content filtering. For example, you might want to filter out certain elements from the HTML response before sending it back to the client, such as blocking tracking scripts or modifying images.
Here’s how to filter out a specific script tag:
python
from bs4 import BeautifulSoup
@app.route(‘/’, methods=[‘GET’])
def proxy_with_filter():
url = request.args.get(‘url’)
if not url:
return “Error: No URL provided”, 400
try:
response = requests.get(url)
# Parse the response content with BeautifulSoup
soup = BeautifulSoup(response.content, ‘html.parser’)
# Remove unwanted script tags
for script in soup.find_all(‘script’):
script.decompose()
# Return the modified content
return Response(str(soup), headers=response.headers, status=response.status_code)
except requests.RequestException as e:
return f”Error: {e}”, 500
In this example, BeautifulSoup is used to parse and modify the HTML content by removing any