from flask import Flask, request, Response
import requests
import re
import urllib.parse
import logging
logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
HOME_PAGE = """
Hello
"""
@app.route('/')
def index():
return HOME_PAGE
@app.route('/go/')
def proxy_path(encoded_url):
try:
# Base64 decode the URL
url = urllib.parse.unquote(encoded_url)
url = str(base64_decode(url))
return proxy_request(url)
except Exception as e:
logging.error(f"Proxy path error: {e}")
return f"Proxy error: {str(e)}", 500
def base64_decode(encoded):
# Add padding to ensure correct decoding
padding = 4 - (len(encoded) % 4)
if padding < 4:
encoded += "=" * padding
try:
return bytes.decode(base64.b64decode(encoded))
except:
try:
# Try URL-safe Base64 decoding
return bytes.decode(base64.urlsafe_b64decode(encoded))
except:
# If decoding fails, return the original value
return encoded
def proxy_request(url):
try:
# If the URL is not a complete HTTP URL, add the protocol
if not url.startswith('http'):
url = 'https://' + url
logging.info(f"Proxying request: {url}")
# Create a session to maintain cookies and state
session = requests.Session()
# Build request headers
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'identity', # Disable compression
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
# Send the request
resp = session.get(url, headers=headers, stream=True, verify=False, timeout=30)
# Get the response content
content = resp.content
content_type = resp.headers.get('Content-Type', 'text/html')
# If it's HTML content, modify all links
if 'text/html' in content_type:
content = rewrite_links(content, url)
# Create the response object
response = Response(content)
# Copy the original response headers
for key, value in resp.headers.items():
if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding',
'connection', 'content-security-policy']:
response.headers[key] = value
return response
except Exception as e:
logging.error(f"Proxy request failed: {e}")
return f"Failed to access {url}: {str(e)}", 500
def rewrite_links(content, base_url):
try:
# Decode the content
content_str = content.decode('utf-8', errors='replace')
# Parse the base URL information
parsed_base = urllib.parse.urlparse(base_url)
base_domain = f"{parsed_base.scheme}://{parsed_base.netloc}"
# Replace all links
def encode_url(url):
# Convert relative URL to absolute URL
if url.startswith('/'):
absolute_url = base_domain + url
elif not url.startswith('http') and not url.startswith('data:') and not url.startswith('#'):
absolute_url = urllib.parse.urljoin(base_url, url)
else:
absolute_url = url
# Encode the URL as Base64 and add the proxy prefix
if absolute_url.startswith('http'):
encoded = base64.b64encode(absolute_url.encode()).decode()
return f"/go/{urllib.parse.quote(encoded)}"
return url
# 1. Replace href attributes
content_str = re.sub(r'href=["\'](.*?)["\']',
lambda m: f'href="{encode_url(m.group(1))}"', content_str)
# 2. Replace src attributes
content_str = re.sub(r'src=["\'](.*?)["\']',
lambda m: f'src="{encode_url(m.group(1))}"', content_str)
# 3. Replace action attributes (forms)
content_str = re.sub(r'action=["\'](.*?)["\']',
lambda m: f'action="{encode_url(m.group(1))}"', content_str)
# 4. Replace URLs in CSS
content_str = re.sub(r'url\([\'"]?(.*?)[\'"]?\)',
lambda m: f'url({encode_url(m.group(1))})', content_str)
# 5. Inject JavaScript handling script
script = """
"""
# Insert the script before the body end tag
if '