Ausgabe der neuen DB Einträge
This commit is contained in:
parent
bad48e1627
commit
cfbbb9ee3d
2399 changed files with 843193 additions and 43 deletions
|
|
@ -0,0 +1,215 @@
|
|||
# -*- test-case-name: twisted.protocols.haproxy.test.test_v2parser -*-
|
||||
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
"""
|
||||
IProxyParser implementation for version two of the PROXY protocol.
|
||||
"""
|
||||
|
||||
import binascii
|
||||
import struct
|
||||
|
||||
from constantly import Values, ValueConstant
|
||||
|
||||
from zope.interface import implementer
|
||||
from twisted.internet import address
|
||||
from twisted.python import compat
|
||||
|
||||
from ._exceptions import (
|
||||
convertError, InvalidProxyHeader, InvalidNetworkProtocol,
|
||||
MissingAddressData
|
||||
)
|
||||
from . import _info
|
||||
from . import _interfaces
|
||||
|
||||
class NetFamily(Values):
|
||||
"""
|
||||
Values for the 'family' field.
|
||||
"""
|
||||
UNSPEC = ValueConstant(0x00)
|
||||
INET = ValueConstant(0x10)
|
||||
INET6 = ValueConstant(0x20)
|
||||
UNIX = ValueConstant(0x30)
|
||||
|
||||
|
||||
|
||||
class NetProtocol(Values):
|
||||
"""
|
||||
Values for 'protocol' field.
|
||||
"""
|
||||
UNSPEC = ValueConstant(0)
|
||||
STREAM = ValueConstant(1)
|
||||
DGRAM = ValueConstant(2)
|
||||
|
||||
|
||||
_HIGH = 0b11110000
|
||||
_LOW = 0b00001111
|
||||
_LOCALCOMMAND = 'LOCAL'
|
||||
_PROXYCOMMAND = 'PROXY'
|
||||
|
||||
@implementer(_interfaces.IProxyParser)
|
||||
class V2Parser(object):
|
||||
"""
|
||||
PROXY protocol version two header parser.
|
||||
|
||||
Version two of the PROXY protocol is a binary format.
|
||||
"""
|
||||
|
||||
PREFIX = b'\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A'
|
||||
VERSIONS = [32]
|
||||
COMMANDS = {0: _LOCALCOMMAND, 1: _PROXYCOMMAND}
|
||||
ADDRESSFORMATS = {
|
||||
# TCP4
|
||||
17: '!4s4s2H',
|
||||
18: '!4s4s2H',
|
||||
# TCP6
|
||||
33: '!16s16s2H',
|
||||
34: '!16s16s2H',
|
||||
# UNIX
|
||||
49: '!108s108s',
|
||||
50: '!108s108s',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.buffer = b''
|
||||
|
||||
|
||||
def feed(self, data):
|
||||
"""
|
||||
Consume a chunk of data and attempt to parse it.
|
||||
|
||||
@param data: A bytestring.
|
||||
@type data: bytes
|
||||
|
||||
@return: A two-tuple containing, in order, a L{_interfaces.IProxyInfo}
|
||||
and any bytes fed to the parser that followed the end of the
|
||||
header. Both of these values are None until a complete header is
|
||||
parsed.
|
||||
|
||||
@raises InvalidProxyHeader: If the bytes fed to the parser create an
|
||||
invalid PROXY header.
|
||||
"""
|
||||
self.buffer += data
|
||||
if len(self.buffer) < 16:
|
||||
raise InvalidProxyHeader()
|
||||
|
||||
size = struct.unpack('!H', self.buffer[14:16])[0] + 16
|
||||
if len(self.buffer) < size:
|
||||
return (None, None)
|
||||
|
||||
header, remaining = self.buffer[:size], self.buffer[size:]
|
||||
self.buffer = b''
|
||||
info = self.parse(header)
|
||||
return (info, remaining)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _bytesToIPv4(bytestring):
|
||||
"""
|
||||
Convert packed 32-bit IPv4 address bytes into a dotted-quad ASCII bytes
|
||||
representation of that address.
|
||||
|
||||
@param bytestring: 4 octets representing an IPv4 address.
|
||||
@type bytestring: L{bytes}
|
||||
|
||||
@return: a dotted-quad notation IPv4 address.
|
||||
@rtype: L{bytes}
|
||||
"""
|
||||
return b'.'.join(
|
||||
('%i' % (ord(b),)).encode('ascii')
|
||||
for b in compat.iterbytes(bytestring)
|
||||
)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _bytesToIPv6(bytestring):
|
||||
"""
|
||||
Convert packed 128-bit IPv6 address bytes into a colon-separated ASCII
|
||||
bytes representation of that address.
|
||||
|
||||
@param bytestring: 16 octets representing an IPv6 address.
|
||||
@type bytestring: L{bytes}
|
||||
|
||||
@return: a dotted-quad notation IPv6 address.
|
||||
@rtype: L{bytes}
|
||||
"""
|
||||
hexString = binascii.b2a_hex(bytestring)
|
||||
return b':'.join(
|
||||
('%x' % (int(hexString[b:b+4], 16),)).encode('ascii')
|
||||
for b in range(0, 32, 4)
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def parse(cls, line):
|
||||
"""
|
||||
Parse a bytestring as a full PROXY protocol header.
|
||||
|
||||
@param line: A bytestring that represents a valid HAProxy PROXY
|
||||
protocol version 2 header.
|
||||
@type line: bytes
|
||||
|
||||
@return: A L{_interfaces.IProxyInfo} containing the
|
||||
parsed data.
|
||||
|
||||
@raises InvalidProxyHeader: If the bytestring does not represent a
|
||||
valid PROXY header.
|
||||
"""
|
||||
prefix = line[:12]
|
||||
addrInfo = None
|
||||
with convertError(IndexError, InvalidProxyHeader):
|
||||
# Use single value slices to ensure bytestring values are returned
|
||||
# instead of int in PY3.
|
||||
versionCommand = ord(line[12:13])
|
||||
familyProto = ord(line[13:14])
|
||||
|
||||
if prefix != cls.PREFIX:
|
||||
raise InvalidProxyHeader()
|
||||
|
||||
version, command = versionCommand & _HIGH, versionCommand & _LOW
|
||||
if version not in cls.VERSIONS or command not in cls.COMMANDS:
|
||||
raise InvalidProxyHeader()
|
||||
|
||||
if cls.COMMANDS[command] == _LOCALCOMMAND:
|
||||
return _info.ProxyInfo(line, None, None)
|
||||
|
||||
family, netproto = familyProto & _HIGH, familyProto & _LOW
|
||||
with convertError(ValueError, InvalidNetworkProtocol):
|
||||
family = NetFamily.lookupByValue(family)
|
||||
netproto = NetProtocol.lookupByValue(netproto)
|
||||
if (
|
||||
family is NetFamily.UNSPEC or
|
||||
netproto is NetProtocol.UNSPEC
|
||||
):
|
||||
return _info.ProxyInfo(line, None, None)
|
||||
|
||||
addressFormat = cls.ADDRESSFORMATS[familyProto]
|
||||
addrInfo = line[16:16+struct.calcsize(addressFormat)]
|
||||
if family is NetFamily.UNIX:
|
||||
with convertError(struct.error, MissingAddressData):
|
||||
source, dest = struct.unpack(addressFormat, addrInfo)
|
||||
return _info.ProxyInfo(
|
||||
line,
|
||||
address.UNIXAddress(source.rstrip(b'\x00')),
|
||||
address.UNIXAddress(dest.rstrip(b'\x00')),
|
||||
)
|
||||
|
||||
addrType = 'TCP'
|
||||
if netproto is NetProtocol.DGRAM:
|
||||
addrType = 'UDP'
|
||||
addrCls = address.IPv4Address
|
||||
addrParser = cls._bytesToIPv4
|
||||
if family is NetFamily.INET6:
|
||||
addrCls = address.IPv6Address
|
||||
addrParser = cls._bytesToIPv6
|
||||
|
||||
with convertError(struct.error, MissingAddressData):
|
||||
info = struct.unpack(addressFormat, addrInfo)
|
||||
source, dest, sPort, dPort = info
|
||||
|
||||
return _info.ProxyInfo(
|
||||
line,
|
||||
addrCls(addrType, addrParser(source), sPort),
|
||||
addrCls(addrType, addrParser(dest), dPort),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue