pypush-plus-plus/proxy/proxy.py

134 lines
3.9 KiB
Python
Raw Normal View History

2023-04-07 00:48:14 -05:00
# TLS server to proxy APNs traffic
import socket
import tlslite
import threading
2023-04-07 15:24:05 -05:00
import sys
# setting path
sys.path.append('../')
2023-04-07 00:48:14 -05:00
# APNs server to proxy traffic to
2023-04-07 12:44:56 -05:00
APNS_HOST = "windows.courier.push.apple.com"
2023-04-07 00:48:14 -05:00
APNS_PORT = 5223
2023-04-07 15:24:05 -05:00
#ALPN = b"apns-security-v3"
ALPN = b"apns-security-v2"
2023-04-07 00:48:14 -05:00
#ALPN = b"apns-pack-v1"
2023-04-07 15:24:05 -05:00
global_cnt = 0
2023-04-07 00:48:14 -05:00
# Connect to the APNs server
def connect() -> tlslite.TLSConnection:
# Connect to the APNs server
sock = socket.create_connection((APNS_HOST, APNS_PORT))
# Wrap the socket in TLS
ssock = tlslite.TLSConnection(sock)
2023-04-07 08:47:21 -05:00
#print("Handshaking with APNs")
2023-04-07 00:48:14 -05:00
# Handshake with the server
2023-04-07 15:24:05 -05:00
if ALPN == b"apns-security-v3":
ssock.handshakeClientCert(alpn=[ALPN])
else:
import albert
private_key, cert = albert.generate_push_cert()
cert = tlslite.X509CertChain([tlslite.X509().parse(cert)])
private_key = tlslite.parsePEMKey(private_key, private=True)
# Handshake with the server
ssock.handshakeClientCert(cert, private_key, alpn=[ALPN])
2023-04-07 00:48:14 -05:00
return ssock
cert:str = None
key:str = None
2023-04-07 08:28:32 -05:00
import apns
import printer
2023-04-07 00:48:14 -05:00
def proxy(conn1: tlslite.TLSConnection, conn2: tlslite.TLSConnection, prefix: str = ""):
2023-04-07 09:33:03 -05:00
try:
while True:
# Read data from the first connection
data = conn1.read()
# If there is no data, the connection has closed
if not data:
break
2023-04-07 00:48:14 -05:00
2023-04-07 09:33:03 -05:00
override = printer.pretty_print_payload(prefix, apns._deserialize_payload_from_buffer(data))
if override is not None:
data = override
print("OVERRIDE: ", end="")
printer.pretty_print_payload(prefix, apns._deserialize_payload_from_buffer(data))
2023-04-07 08:28:32 -05:00
2023-04-07 09:33:03 -05:00
#print(prefix, data)
# Write the data to the second connection
conn2.write(data)
2023-04-07 11:19:44 -05:00
except OSError as e:
if e.errno == 9:
pass # Probably a connection closed error
2023-04-07 12:44:56 -05:00
except tlslite.TLSAbruptCloseError:
pass
2023-04-07 00:48:14 -05:00
print("Connection closed")
# Close the connections
conn1.close()
conn2.close()
def handle(conn: socket.socket):
# Wrap the socket in TLS
s_conn = tlslite.TLSConnection(conn)
global cert, key
chain = tlslite.X509CertChain()
chain.parsePemList(cert)
2023-04-07 08:47:21 -05:00
#print(chain)
2023-04-07 00:48:14 -05:00
#cert = tlslite.X509CertChain([tlslite.X509().parse(cert)])
key_parsed = tlslite.parsePEMKey(key, private=True)
2023-04-07 08:47:21 -05:00
#print(key_parsed)
2023-04-07 00:48:14 -05:00
s_conn.handshakeServer(certChain=chain, privateKey=key_parsed, reqCert=False, alpn=[ALPN])
print("Handling connection")
# Connect to the APNs server
apns = connect()
print("Connected to APNs")
2023-04-07 15:24:05 -05:00
global global_cnt
global_cnt += 1
2023-04-07 00:48:14 -05:00
# Proxy data between the connections
# Create a thread to proxy data from the APNs server to the client
2023-04-07 15:24:05 -05:00
threading.Thread(target=proxy, args=(s_conn, apns, f"{global_cnt} apsd -> APNs")).start()
2023-04-07 00:48:14 -05:00
# Just proxy data from the client to the APNs server in this thread
2023-04-07 15:24:05 -05:00
proxy(apns, s_conn, f"{global_cnt} APNs -> apsd")
2023-04-07 00:48:14 -05:00
def serve():
# Create a socket to listen for connections
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("localhost", 5223))
sock.listen()
print("Listening for connections...")
# Handshake with the client
# Read the certificate and private key from the config
with open("push_certificate_chain.pem", "r") as f:
global cert
cert = f.read()
# NEED TO USE OPENSSL, SEE CORETRUST CMD, MIMIC ENTRUST? OR AT LEAST SEE PUSHPROXY FOR EXTRACTION & REPLACEMENT
with open("push_key.pem", "r") as f:
global key
key = f.read()
# Accept connections
while True:
# Accept a connection
conn, addr = sock.accept()
# Create a thread to handle the connection
#handle(conn)
thread = threading.Thread(target=handle, args=(conn,))
thread.start()
if __name__ == "__main__":
serve()