mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 14:58:38 +00:00
First draft of OSX transparent proxy mode.
This commit is contained in:
parent
5347cb9c26
commit
e2dc7ba09d
@ -1,103 +1,20 @@
|
||||
import socket, ctypes
|
||||
|
||||
# Python socket module does not have this constant
|
||||
DIOCNATLOOK = 23
|
||||
PFDEV = "/dev/pf"
|
||||
|
||||
|
||||
class PF_STATE_XPORT(ctypes.Union):
|
||||
"""
|
||||
union pf_state_xport {
|
||||
u_int16_t port;
|
||||
u_int16_t call_id;
|
||||
u_int32_t spi;
|
||||
};
|
||||
"""
|
||||
_fields_ = [
|
||||
("port", ctypes.c_uint),
|
||||
("call_id", ctypes.c_uint),
|
||||
("spi", ctypes.c_ulong),
|
||||
]
|
||||
|
||||
|
||||
class PF_ADDR(ctypes.Union):
|
||||
"""
|
||||
struct pf_addr {
|
||||
union {
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
u_int8_t addr8[16];
|
||||
u_int16_t addr16[8];
|
||||
u_int32_t addr32[4];
|
||||
} pfa;
|
||||
}
|
||||
"""
|
||||
_fields_ = [
|
||||
("addr8", ctypes.c_byte * 2),
|
||||
("addr16", ctypes.c_byte * 4),
|
||||
("addr32", ctypes.c_byte * 8),
|
||||
]
|
||||
|
||||
|
||||
class PFIOC_NATLOOK(ctypes.Structure):
|
||||
"""
|
||||
struct pfioc_natlook {
|
||||
struct pf_addr saddr;
|
||||
struct pf_addr daddr;
|
||||
struct pf_addr rsaddr;
|
||||
struct pf_addr rdaddr;
|
||||
#ifndef NO_APPLE_EXTENSIONS
|
||||
union pf_state_xport sxport;
|
||||
union pf_state_xport dxport;
|
||||
union pf_state_xport rsxport;
|
||||
union pf_state_xport rdxport;
|
||||
sa_family_t af;
|
||||
u_int8_t proto;
|
||||
u_int8_t proto_variant;
|
||||
u_int8_t direction;
|
||||
#else
|
||||
u_int16_t sport;
|
||||
u_int16_t dport;
|
||||
u_int16_t rsport;
|
||||
u_int16_t rdport;
|
||||
sa_family_t af;
|
||||
u_int8_t proto;
|
||||
u_int8_t direction;
|
||||
#endif
|
||||
};
|
||||
"""
|
||||
_fields_ = [
|
||||
("saddr", PF_ADDR),
|
||||
("daddr", PF_ADDR),
|
||||
("rsaddr", PF_ADDR),
|
||||
("rdaddr", PF_ADDR),
|
||||
|
||||
("sxport", PF_STATE_XPORT),
|
||||
("dxport", PF_STATE_XPORT),
|
||||
("rsxport", PF_STATE_XPORT),
|
||||
("rdxport", PF_STATE_XPORT),
|
||||
("af", ctypes.c_uint),
|
||||
("proto", ctypes.c_ushort),
|
||||
("proto_variant", ctypes.c_ushort),
|
||||
("direction", ctypes.c_ushort),
|
||||
]
|
||||
import subprocess
|
||||
import pf
|
||||
|
||||
"""
|
||||
Doing this the "right" way by using DIOCNATLOOK on the pf device turns out
|
||||
to be a pain. Apple has made a number of modifications to the data
|
||||
structures returned, and compiling userspace tools to test and work with
|
||||
this turns out to be a pain in the ass. Parsing pfctl output is short,
|
||||
simple, and works.
|
||||
"""
|
||||
|
||||
class Resolver:
|
||||
STATECMD = ("sudo", "-n", "/sbin/pfctl", "-s", "state")
|
||||
def __init__(self):
|
||||
self.pfdev = open(PFDEV, "r")
|
||||
pass
|
||||
|
||||
def original_addr(self, csock):
|
||||
"""
|
||||
The following sttruct defintions are plucked from the current XNU source, found here:
|
||||
|
||||
http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/bsd/net/pfvar.h
|
||||
|
||||
|
||||
union pf_state_xport {
|
||||
u_int16_t port;
|
||||
u_int16_t call_id;
|
||||
u_int32_t spi;
|
||||
};
|
||||
"""
|
||||
pass
|
||||
peer = csock.getpeername()
|
||||
stxt = subprocess.check_output(self.STATECMD, stderr=subprocess.STDOUT)
|
||||
return pf.lookup(peer[0], peer[1], stxt)
|
||||
|
16
libmproxy/platform/pf.py
Normal file
16
libmproxy/platform/pf.py
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
def lookup(address, port, s):
|
||||
"""
|
||||
Parse the pfctl state output s, to look up the destination host
|
||||
matching the client (address, port).
|
||||
|
||||
Returns an (address, port) tuple, or None.
|
||||
"""
|
||||
spec = "%s:%s"%(address, port)
|
||||
for i in s.split("\n"):
|
||||
if "ESTABLISHED:ESTABLISHED" in i and spec in i:
|
||||
s = i.split()
|
||||
if len(s) > 4:
|
||||
s = s[4].split(":")
|
||||
if len(s) == 2:
|
||||
return s[0], int(s[1])
|
4
test/data/pf01
Normal file
4
test/data/pf01
Normal file
@ -0,0 +1,4 @@
|
||||
No ALTQ support in kernel
|
||||
ALTQ related functions disabled
|
||||
ALL tcp 127.0.0.1:8080 <- 5.5.5.6:80 <- 192.168.1.111:40001 FIN_WAIT_2:FIN_WAIT_2
|
||||
ALL tcp 127.0.0.1:8080 <- 5.5.5.5:80 <- 192.168.1.111:40000 ESTABLISHED:ESTABLISHED
|
13
test/test_platform_pf.py
Normal file
13
test/test_platform_pf.py
Normal file
@ -0,0 +1,13 @@
|
||||
import tutils
|
||||
from libmproxy.platform import pf
|
||||
|
||||
|
||||
class TestLookup:
|
||||
def test_simple(self):
|
||||
p = tutils.test_data.path("data/pf01")
|
||||
d = open(p).read()
|
||||
assert pf.lookup("192.168.1.111", 40000, d) == ("5.5.5.5", 80)
|
||||
assert not pf.lookup("192.168.1.112", 40000, d)
|
||||
assert not pf.lookup("192.168.1.111", 40001, d)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user