def test_parse_tcp_packet():
data = bytes.fromhex(
'4500 007e 5376 4000 4006 62c7 ac10 2a65'
'acd9 00ee b506 0050 9933 d7ed 8c4e f15b'
'8018 00e5 0238 0000 0101 080a 8502 aff1'
'c7cc 571a 4745 5420 2f20 4854 5450 2f31'
'2e31 0d0a 486f 7374 3a20 676f 6f67 6c65'
'2e63 6f6d 0d0a 5573 6572 2d41 6765 6e74'
'3a20 6375 726c 2f37 2e35 342e 310d 0a41'
'6363 6570 743a 202a 2f2a 0d0a 0d0a'
)
ipv4 = pnet.parse('ipv4', data)
assert ipv4.readonly
assert ipv4['src'] == IPv4Address('172.16.42.101').packed
assert ipv4['dst'] == IPv4Address('172.217.0.238').packed
assert ipv4['p'] == socket.IPPROTO_TCP
assert ipv4['len'] == 126
tcp = ipv4.parse('tcp')
assert tcp.readonly
assert tcp['sport'] == 46342
assert tcp['dport'] == 80
payload = tcp.payload
assert payload.readonly
assert payload == (b'GET / HTTP/1.1\r\n'
b'Host: google.com\r\n'
b'User-Agent: curl/7.54.1\r\n'
b'Accept: */*\r\n'
b'\r\n')
python类IPPROTO_TCP的实例源码
def handle_write(self):
if self.needs_config:
self.needs_config = False
self.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 128 * 1024)
self.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 128 * 1024)
if len(self.buffer) > 0:
sent = self.send(self.buffer)
logging.debug('[{0:d}] TCP => {1:d} byte(s)'.format(self.client_id, sent))
self.buffer = self.buffer[sent:]
if self.needs_close and len(self.buffer) == 0:
self.needs_close = False
self.handle_close()
def __init__(self, connected_socket, client_id):
global options
asyncore.dispatcher.__init__(self, connected_socket)
self.client_id = client_id
self.state = self.STATE_WAITING_FOR_HANDSHAKE
self.ip = None
self.addresses = None
self.hostname = None
self.port = None
self.requested_address = None
self.buffer = ''
self.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 128 * 1024)
self.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 128 * 1024)
self.needs_close = False
def _connect(self):
"Create a TCP socket connection"
# we want to mimic what socket.create_connection does to support
# ipv4/ipv6, but we want to set options prior to calling
# socket.connect()
err = None
for res in socket.getaddrinfo(self.host, self.port, 0,
socket.SOCK_STREAM):
family, socktype, proto, canonname, socket_address = res
sock = None
try:
sock = socket.socket(family, socktype, proto)
# TCP_NODELAY
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# TCP_KEEPALIVE
if self.socket_keepalive:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
for k, v in iteritems(self.socket_keepalive_options):
sock.setsockopt(socket.SOL_TCP, k, v)
# set the socket_connect_timeout before we connect
sock.settimeout(self.socket_connect_timeout)
# connect
sock.connect(socket_address)
# set the socket_timeout now that we're connected
sock.settimeout(self.socket_timeout)
return sock
except socket.error as _:
err = _
if sock is not None:
sock.close()
if err is not None:
raise err
raise socket.error("socket.getaddrinfo returned an empty list")
def setup(self):
self.connection = self.request
if self.timeout is not None:
self.connection.settimeout(self.timeout)
if self.disable_nagle_algorithm:
self.connection.setsockopt(socket.IPPROTO_TCP,
socket.TCP_NODELAY, True)
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.wfile = self.connection.makefile('wb', self.wbufsize)
def _write_SOCKS5_address(self, addr, file):
"""
Return the host and port packed for the SOCKS5 protocol,
and the resolved address as a tuple object.
"""
host, port = addr
proxy_type, _, _, rdns, username, password = self.proxy
family_to_byte = {socket.AF_INET: b"\x01", socket.AF_INET6: b"\x04"}
# If the given destination address is an IP address, we'll
# use the IP address request even if remote resolving was specified.
# Detect whether the address is IPv4/6 directly.
for family in (socket.AF_INET, socket.AF_INET6):
try:
addr_bytes = socket.inet_pton(family, host)
file.write(family_to_byte[family] + addr_bytes)
host = socket.inet_ntop(family, addr_bytes)
file.write(struct.pack(">H", port))
return host, port
except socket.error:
continue
# Well it's not an IP number, so it's probably a DNS name.
if rdns:
# Resolve remotely
host_bytes = host.encode("idna")
file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes)
else:
# Resolve locally
addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG)
# We can't really work out what IP is reachable, so just pick the
# first.
target_addr = addresses[0]
family = target_addr[0]
host = target_addr[4][0]
addr_bytes = socket.inet_pton(family, host)
file.write(family_to_byte[family] + addr_bytes)
host = socket.inet_ntop(family, addr_bytes)
file.write(struct.pack(">H", port))
return host, port
def make_conn(bld, srv):
#port = PORT + idx
port = srv.port
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
conn.connect(('127.0.0.1', port))
return conn
def create_server(conn, cls):
# child processes do not need the key, so we remove it from the OS environment
global SHARED_KEY
SHARED_KEY = os.environ['SHARED_KEY']
os.environ['SHARED_KEY'] = ''
ppid = int(os.environ['PREFORKPID'])
def reap():
if os.sep != '/':
os.waitpid(ppid, 0)
else:
while 1:
try:
os.kill(ppid, 0)
except OSError:
break
else:
time.sleep(1)
os.kill(os.getpid(), signal.SIGKILL)
t = threading.Thread(target=reap)
t.setDaemon(True)
t.start()
server = SocketServer.TCPServer(conn, req)
print(server.server_address[1])
sys.stdout.flush()
#server.timeout = 6000 # seconds
server.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
try:
server.serve_forever(poll_interval=0.001)
except KeyboardInterrupt:
pass
def make_conn(bld, srv):
port = srv.port
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
conn.connect(('127.0.0.1', port))
return conn
def make_conn(bld, srv):
#port = PORT + idx
port = srv.port
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
conn.connect(('127.0.0.1', port))
return conn
def create_server(conn, cls):
# child processes do not need the key, so we remove it from the OS environment
global SHARED_KEY
SHARED_KEY = os.environ['SHARED_KEY']
os.environ['SHARED_KEY'] = ''
ppid = int(os.environ['PREFORKPID'])
def reap():
if os.sep != '/':
os.waitpid(ppid, 0)
else:
while 1:
try:
os.kill(ppid, 0)
except OSError:
break
else:
time.sleep(1)
os.kill(os.getpid(), signal.SIGKILL)
t = threading.Thread(target=reap)
t.setDaemon(True)
t.start()
server = SocketServer.TCPServer(conn, req)
print(server.server_address[1])
sys.stdout.flush()
#server.timeout = 6000 # seconds
server.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
try:
server.serve_forever(poll_interval=0.001)
except KeyboardInterrupt:
pass
def make_conn(bld, srv):
#port = PORT + idx
port = srv.port
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
conn.connect(('127.0.0.1', port))
return conn
def create_server(conn, cls):
# child processes do not need the key, so we remove it from the OS environment
global SHARED_KEY
SHARED_KEY = os.environ['SHARED_KEY']
os.environ['SHARED_KEY'] = ''
ppid = int(os.environ['PREFORKPID'])
def reap():
if os.sep != '/':
os.waitpid(ppid, 0)
else:
while 1:
try:
os.kill(ppid, 0)
except OSError:
break
else:
time.sleep(1)
os.kill(os.getpid(), signal.SIGKILL)
t = threading.Thread(target=reap)
t.setDaemon(True)
t.start()
server = SocketServer.TCPServer(conn, req)
print(server.server_address[1])
sys.stdout.flush()
#server.timeout = 6000 # seconds
server.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
try:
server.serve_forever(poll_interval=0.001)
except KeyboardInterrupt:
pass
def make_conn(bld, srv):
port = srv.port
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
conn.connect(('127.0.0.1', port))
return conn
def __init__(self, source, destination, payload='', proto=socket.IPPROTO_TCP):
self.version = 4
self.ihl = 5 # Internet Header Length
self.tos = 0 # Type of Service
self.tl = 20+len(payload)
self.id = 0#random.randint(0, 65535)
self.flags = 0 # Don't fragment
self.offset = 0
self.ttl = 255
self.protocol = proto
self.checksum = 2 # will be filled by kernel
self.source = socket.inet_aton(source)
self.destination = socket.inet_aton(destination)
def pack(self, source, destination):
data_offset = (self.offset << 4) + 0
flags = self.fin + (self.syn << 1) + (self.rst << 2) + (self.psh << 3) + (self.ack << 4) + (self.urg << 5)
tcp_header = struct.pack('!HHLLBBHHH',
self.srcp,
self.dstp,
self.seqn,
self.ackn,
data_offset,
flags,
self.window,
self.checksum,
self.urgp)
#pseudo header fields
source_ip = source
destination_ip = destination
reserved = 0
protocol = socket.IPPROTO_TCP
total_length = len(tcp_header) + len(self.payload)
# Pseudo header
psh = struct.pack("!4s4sBBH",
source_ip,
destination_ip,
reserved,
protocol,
total_length)
psh = psh + tcp_header + self.payload
tcp_checksum = checksum(psh)
tcp_header = struct.pack("!HHLLBBH",
self.srcp,
self.dstp,
self.seqn,
self.ackn,
data_offset,
flags,
self.window)
tcp_header+= struct.pack('H', tcp_checksum) + struct.pack('!H', self.urgp)
return tcp_header
def _connect(self):
"Create a TCP socket connection"
# we want to mimic what socket.create_connection does to support
# ipv4/ipv6, but we want to set options prior to calling
# socket.connect()
err = None
for res in socket.getaddrinfo(self.host, self.port, 0,
socket.SOCK_STREAM):
family, socktype, proto, canonname, socket_address = res
sock = None
try:
sock = socket.socket(family, socktype, proto)
# TCP_NODELAY
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# TCP_KEEPALIVE
if self.socket_keepalive:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
for k, v in iteritems(self.socket_keepalive_options):
sock.setsockopt(socket.SOL_TCP, k, v)
# set the socket_connect_timeout before we connect
sock.settimeout(self.socket_connect_timeout)
# connect
sock.connect(socket_address)
# set the socket_timeout now that we're connected
sock.settimeout(self.socket_timeout)
return sock
except socket.error as _:
err = _
if sock is not None:
sock.close()
if err is not None:
raise err
raise socket.error("socket.getaddrinfo returned an empty list")
def set_nodelay(self, value):
if (self.socket is not None and
self.socket.family in (socket.AF_INET, socket.AF_INET6)):
try:
self.socket.setsockopt(socket.IPPROTO_TCP,
socket.TCP_NODELAY, 1 if value else 0)
except socket.error as e:
# Sometimes setsockopt will fail if the socket is closed
# at the wrong time. This can happen with HTTPServer
# resetting the value to false between requests.
if e.errno != errno.EINVAL and not self._is_connreset(e):
raise
def _connect(self):
"Create a TCP socket connection"
# we want to mimic what socket.create_connection does to support
# ipv4/ipv6, but we want to set options prior to calling
# socket.connect()
err = None
for res in socket.getaddrinfo(self.host, self.port, 0,
socket.SOCK_STREAM):
family, socktype, proto, canonname, socket_address = res
sock = None
try:
sock = socket.socket(family, socktype, proto)
# TCP_NODELAY
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# TCP_KEEPALIVE
if self.socket_keepalive:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
for k, v in iteritems(self.socket_keepalive_options):
sock.setsockopt(socket.SOL_TCP, k, v)
# set the socket_connect_timeout before we connect
sock.settimeout(self.socket_connect_timeout)
# connect
sock.connect(socket_address)
# set the socket_timeout now that we're connected
sock.settimeout(self.socket_timeout)
return sock
except socket.error as _:
err = _
if sock is not None:
sock.close()
if err is not None:
raise err
raise socket.error("socket.getaddrinfo returned an empty list")
def set_nodelay(self, value):
if (self.socket is not None and
self.socket.family in (socket.AF_INET, socket.AF_INET6)):
try:
self.socket.setsockopt(socket.IPPROTO_TCP,
socket.TCP_NODELAY, 1 if value else 0)
except socket.error as e:
# Sometimes setsockopt will fail if the socket is closed
# at the wrong time. This can happen with HTTPServer
# resetting the value to false between requests.
if e.errno != errno.EINVAL and not self._is_connreset(e):
raise