Ejemplo n.º 1
0
    def test_upnp_mapper(self):
        from shtoom.upnp import UPnPMapper
        ae = self.assertEqual
        ar = self.assertRaises
        checkUPnP()
        mapper = UPnPMapper()
        uprot = DatagramProtocol()
        uport = reactor.listenUDP(random.randint(10000, 20000), uprot)

        class tfactory(Factory):
            protocol = Protocol

        tport = reactor.listenTCP(0, tfactory())
        for port in uport, tport:
            ar(ValueError, mapper.unmap, port)
            ar(ValueError, mapper.info, port)
            t = TestMapper(mapper, port)
            d = t.go()
            util.wait(d, timeout=16)
            ae(len(t.map_res), 2)
            ae(t.map_res, t.info_res)
            ae(t.unmap_res, None)
            # Can't unmap a port that's not mapped
            ar(ValueError, mapper.unmap, port)
            d = port.stopListening()
            util.wait(d)
            # Can't map a closed port
            ar(ValueError, mapper.map, port)
            # Can't get info on a closed port
            ar(ValueError, mapper.info, port)
Ejemplo n.º 2
0
 def test_str(self):
     """
     C{str()} on the listening port object includes the port number.
     """
     reactor = self.buildReactor()
     port = reactor.listenUDP(0, DatagramProtocol())
     self.assertIn(str(port.getHost().port), str(port))
Ejemplo n.º 3
0
 def test_interface(self):
     """
     L{IReactorUDP.listenUDP} returns an object providing L{IListeningPort}.
     """
     reactor = self.buildReactor()
     port = reactor.listenUDP(0, DatagramProtocol())
     self.assertTrue(verifyObject(IListeningPort, port))
Ejemplo n.º 4
0
    def test_stopOnlyCloses(self):
        """
        When the L{IListeningPort} returned by
        L{IReactorSocket.adoptDatagramPort} is stopped using
        C{stopListening}, the underlying socket is closed but not
        shutdown.  This allows another process which still has a
        reference to it to continue reading and writing to it.
        """
        reactor = self.buildReactor()

        portSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.addCleanup(portSocket.close)

        portSocket.setblocking(False)

        # The file descriptor is duplicated by adoptDatagramPort
        port = reactor.adoptDatagramPort(portSocket.fileno(),
                                         portSocket.family, DatagramProtocol())
        d = port.stopListening()

        def stopped(ignored):
            # Should still be possible to recv on portSocket.  If
            # it was shutdown, the exception would be EINVAL instead.
            exc = self.assertRaises(socket.error, portSocket.recvfrom, 1)
            self.assertEqual(exc.args[0], errno.EAGAIN)

        d.addCallback(stopped)
        d.addErrback(err, "Failed to read on original port.")

        needsRunningReactor(
            reactor, lambda: d.addCallback(lambda ignored: reactor.stop()))

        reactor.run()
Ejemplo n.º 5
0
def get_local_ip_for(target):
    """Find out what our IP address is for use by a given target.

    @return: the IP address as a dotted-quad string which could be used by
              to connect to us. It might work for them, it might not. If
              there is no suitable address (perhaps we don't currently have an
              externally-visible interface), this will return None.
    """

    try:
        target_ipaddr = socket.gethostbyname(target)
    except socket.gaierror:
        # DNS isn't running, or somehow we encountered an error

        # note: if an interface is configured and up, but nothing is connected to it,
        # gethostbyname("A.ROOT-SERVERS.NET") will take 20 seconds to raise socket.gaierror
        # . This is synchronous and occurs for each node being started, so users of certain unit
        # tests will see something like 120s of delay, which may be enough to hit the default
        # trial timeouts. For that reason, get_local_addresses_async() was changed to default to
        # the numerical ip address for A.ROOT-SERVERS.NET, to avoid this DNS lookup. This also
        # makes node startup a tad faster.

        return None
    udpprot = DatagramProtocol()
    port = reactor.listenUDP(0, udpprot)
    try:
        udpprot.transport.connect(target_ipaddr, 7)
        localip = udpprot.transport.getHost().host
    except socket.error:
        # no route to that host
        localip = None
    port.stopListening()  # note, this returns a Deferred
    return localip
Ejemplo n.º 6
0
    def parser(self):
        """
        Get a function for parsing a datagram read from a I{tun} device.

        @return: A function which accepts a datagram exactly as might be read
            from a I{tun} device.  The datagram is expected to ultimately carry
            a UDP datagram.  When called, it returns a L{list} of L{tuple}s.
            Each tuple has the UDP application data as the first element and
            the sender address as the second element.
        """
        datagrams = []
        receiver = DatagramProtocol()

        def capture(*args):
            datagrams.append(args)

        receiver.datagramReceived = capture

        udp = RawUDPProtocol()
        udp.addProto(12345, receiver)

        ip = IPProtocol()
        ip.addProto(17, udp)

        def parse(data):
            # TUN devices omit the ethernet framing so we can start parsing
            # right at the IP layer.
            ip.datagramReceived(data, False, None, None, None)
            return datagrams

        return parse
def get_local_ip():
    """
    Returns a deferred which will be called with a
    2-uple (lan_flag, ip_address) :
        - lan_flag:
            - True if it's a local network (RFC1918)
            - False if it's a WAN address
        
        - ip_address is the actual ip address
    
    @return: A deferred called with the above defined tuple
    @rtype: L{twisted.internet.defer.Deferred}
    """
    # first we try a connected udp socket, then via multicast
    logging.debug("Resolving dns to get udp ip")
    try:
        ipaddr = yield reactor.resolve('A.ROOT-SERVERS.NET')
    except:
        pass
    else:
        udpprot = DatagramProtocol()
        port = reactor.listenUDP(0, udpprot)
        udpprot.transport.connect(ipaddr, 7)
        localip = udpprot.transport.getHost().host
        port.stopListening()

        if is_bogus_ip(localip):
            raise RuntimeError, "Invalid IP address returned"
        else:
            defer.returnValue((is_rfc1918_ip(localip), localip))

    logging.debug("Multicast ping to retrieve local IP")
    ipaddr = yield _discover_multicast()
    defer.returnValue((is_rfc1918_ip(ipaddr), ipaddr))
Ejemplo n.º 8
0
def _getLocalIPAddressViaConnectedUDP(ip):
    from twisted.internet import reactor
    from twisted.internet.protocol import DatagramProtocol
    if _Debug: print "connecting UDP socket to", ip

    print "connecting UDP socket to", ip
    prot = DatagramProtocol()
    p = reactor.listenUDP(0, prot)
    res = prot.transport.connect(ip, 7)
    locip = prot.transport.getHost().host
    p.stopListening()
    del prot, p

    if _Debug: print "connected UDP socket says", locip

    print "connected UDP socket says", locip

    if isBogusAddress(locip):
        # #$#*(&??!@#$!!!
        if _Debug:
            print "connected UDP socket gives crack, trying mcast instead"

        print "connected UDP socket gives crack, trying mcast instead"

        return _getLocalIPAddressViaMulticast()
    else:
        return locip
Ejemplo n.º 9
0
 def test_deprecatedListenMode(self):
     """
     Passing any value for the C{mode} parameter of L{listenUNIXDatagram}
     causes a deprecation warning to be emitted.
     """
     self._deprecatedModeTest('IReactorUNIXDatagram', 'listenUNIXDatagram',
                              self.mktemp(), DatagramProtocol())
Ejemplo n.º 10
0
 def test_repr(self):
     """
     C{repr()} on the listening port object includes the port number.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol())
     self.assertIn(repr(port.getHost().port), str(port))
Ejemplo n.º 11
0
 def test_writingToIPv6OnIPv4RaisesInvalidAddressError(self):
     """
     Writing to an IPv6 address on an IPv4 socket will raise an
     L{InvalidAddressError}.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol(), interface="127.0.0.1")
     self.assertRaises(error.InvalidAddressError, port.write, "spam", ("::1", 1))
Ejemplo n.º 12
0
def determine_ip_for_host(host):
    """Determine local IP address used to communicate with a particular host"""
    test_sock = DatagramProtocol()
    test_sock_listener = reactor.listenUDP(0, test_sock)  # pylint: disable=no-member
    test_sock.transport.connect(host, 1900)
    my_ip = test_sock.transport.getHost().host
    test_sock_listener.stopListening()
    return my_ip
Ejemplo n.º 13
0
 def test_connectingToHostnameRaisesInvalidAddressError(self):
     """
     Connecting to a hostname instead of an IP address will raise an
     L{InvalidAddressError}.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol())
     self.assertRaises(error.InvalidAddressError, port.connect, "example.invalid", 1)
Ejemplo n.º 14
0
def main():
    global config
    parser = argparse.ArgumentParser(description='mitm6 - pwning IPv4 via IPv6\nFor help or reporting issues, visit https://github.com/fox-it/mitm6', formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("-i", "--interface", type=str, metavar='INTERFACE', help="Interface to use (default: autodetect)")
    parser.add_argument("-l", "--localdomain", type=str, metavar='LOCALDOMAIN', help="Domain name to use as DNS search domain (default: use first DNS domain)")
    parser.add_argument("-4", "--ipv4", type=str, metavar='ADDRESS', help="IPv4 address to send packets from (default: autodetect)")
    parser.add_argument("-6", "--ipv6", type=str, metavar='ADDRESS', help="IPv6 link-local address to send packets from (default: autodetect)")
    parser.add_argument("-m", "--mac", type=str, metavar='ADDRESS', help="Custom mac address - probably breaks stuff (default: mac of selected interface)")
    parser.add_argument("-a", "--no-ra", action='store_true', help="Do not advertise ourselves (useful for networks which detect rogue Router Advertisements)")
    parser.add_argument("-v", "--verbose", action='store_true', help="Show verbose information")
    parser.add_argument("--debug", action='store_true', help="Show debug information")

    filtergroup = parser.add_argument_group("Filtering options")
    filtergroup.add_argument("-d", "--domain", action='append', default=[], metavar='DOMAIN', help="Domain name to filter DNS queries on (Whitelist principle, multiple can be specified.)")
    filtergroup.add_argument("-b", "--blacklist", action='append', default=[], metavar='DOMAIN', help="Domain name to filter DNS queries on (Blacklist principle, multiple can be specified.)")
    filtergroup.add_argument("-hw", "--host-whitelist", action='append', default=[], metavar='DOMAIN', help="Hostname (FQDN) to filter DHCPv6 queries on (Whitelist principle, multiple can be specified.)")
    filtergroup.add_argument("-hb", "--host-blacklist", action='append', default=[], metavar='DOMAIN', help="Hostname (FQDN) to filter DHCPv6 queries on (Blacklist principle, multiple can be specified.)")
    filtergroup.add_argument("--ignore-nofqdn", action='store_true', help="Ignore DHCPv6 queries that do not contain the Fully Qualified Domain Name (FQDN) option.")

    args = parser.parse_args()
    config = Config(args)

    print('Starting mitm6 using the following configuration:')
    print('Primary adapter: %s [%s]' % (config.default_if, config.selfmac))
    print('IPv4 address: %s' % config.selfipv4)
    print('IPv6 address: %s' % config.selfaddr)
    if config.localdomain is not None:
        print('DNS local search domain: %s' % config.localdomain)
    if not config.dns_whitelist and not config.dns_blacklist:
        print('Warning: Not filtering on any domain, mitm6 will reply to all DNS queries.\nUnless this is what you want, specify at least one domain with -d')
    else:
        if not config.dns_whitelist:
            print('DNS whitelist: *')
        else:
            print('DNS whitelist: %s' % ', '.join(config.dns_whitelist))
        if config.dns_blacklist:
            print('DNS blacklist: %s' % ', '.join(config.dns_blacklist))
    if config.host_whitelist:
        print('Hostname whitelist: %s' % ', '.join(config.host_whitelist))
    if config.host_blacklist:
        print('Hostname blacklist: %s' % ', '.join(config.host_blacklist))

    #Main packet capture thread
    d = threads.deferToThread(sniff, iface=config.default_if, filter="ip6 proto \\udp or arp or udp port 53", prn=lambda x: reactor.callFromThread(parsepacket, x), stop_filter=should_stop)
    d.addErrback(print_err)

    #RA loop
    if not args.no_ra:
        loop = task.LoopingCall(send_ra)
        d = loop.start(30.0)
        d.addErrback(print_err)

    # Set up DNS
    dnssock = setupFakeDns()
    reactor.adoptDatagramPort(dnssock.fileno(), socket.AF_INET6, DatagramProtocol())

    reactor.addSystemEventTrigger('before', 'shutdown', shutdownnotice)
    reactor.run()
Ejemplo n.º 15
0
 def test_writingToHostnameRaisesInvalidAddressError(self):
     """
     Writing to a hostname instead of an IP address will raise an
     L{InvalidAddressError}.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol())
     self.assertRaises(error.InvalidAddressError, port.write, 'spam',
                       ('example.invalid', 1))
Ejemplo n.º 16
0
 def test_invalidInterface(self):
     """
     An L{InvalidAddressError} is raised when trying to listen on an address
     that isn't a valid IPv4 or IPv6 address.
     """
     reactor = self.buildReactor()
     self.assertRaises(
         error.InvalidAddressError, reactor.listenUDP, DatagramProtocol(),
         0, interface='example.com')
Ejemplo n.º 17
0
 def test_allowBroadcast(self):
     """
     L{IListeningPort.setBroadcastAllowed} sets broadcast to be allowed
     on the socket.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol())
     port.setBroadcastAllowed(True)
     self.assertTrue(port.getBroadcastAllowed())
Ejemplo n.º 18
0
def determine_ip_for_host(host=None):
    """Determine local IP address used to communicate with a particular host"""
    if (host == None):
        host = '192.168.1.1'
    test_sock = DatagramProtocol()
    test_sock_listener = reactor.listenUDP(0, test_sock)
    test_sock.transport.connect(host, 1900)
    my_ip = test_sock.transport.getHost().host
    test_sock_listener.stopListening()
    return my_ip
Ejemplo n.º 19
0
 def test_getHostIPv6(self):
     """
     L{IListeningPort.getHost} returns an L{IPv6Address} when listening on
     an IPv6 interface.
     """
     reactor = self.buildReactor()
     port = self.getListeningPort(reactor, DatagramProtocol(), interface="::1")
     addr = port.getHost()
     self.assertEqual(addr.host, "::1")
     self.assertIsInstance(addr, IPv6Address)
Ejemplo n.º 20
0
 def send_notify(self):
     logger.debug("Sending NOTIFY...")
     # msg = NO % (SSDP_ADDR, SSDP_PORT)
     msg = self.getNotifyMessage()
     port = reactor.listenUDP(9999,
                              DatagramProtocol(),
                              interface=self.iface)
     port.write(utils.build_message(msg),
                (constants.SSDP_ADDR, constants.SSDP_PORT))
     port.stopListening()
Ejemplo n.º 21
0
 def test_listenOnLinuxAbstractNamespace(self):
     """
     On Linux, a UNIX socket path may begin with C{'\0'} to indicate a socket
     in the abstract namespace.  L{IReactorUNIX.listenUNIXDatagram} accepts
     such a path.
     """
     path = _abstractPath(self)
     reactor = self.buildReactor()
     port = reactor.listenUNIXDatagram('\0' + path, DatagramProtocol())
     self.assertEqual(port.getHost(), UNIXAddress('\0' + path))
Ejemplo n.º 22
0
 def test_getHost(self):
     """
     L{IListeningPort.getHost} returns an L{IPv4Address} giving a
     dotted-quad of the IPv4 address the port is listening on as well as
     the port number.
     """
     host, portNumber = findFreePort(type=SOCK_DGRAM)
     reactor = self.buildReactor()
     port = reactor.listenUDP(portNumber,
                              DatagramProtocol(),
                              interface=host)
     self.assertEqual(port.getHost(), IPv4Address('UDP', host, portNumber))
Ejemplo n.º 23
0
    def test_invalidAddressFamily(self):
        """
        An implementation of L{IReactorSocket.adoptDatagramPort} raises
        L{UnsupportedAddressFamily} if passed an address family it does not
        support.
        """
        reactor = self.buildReactor()

        port = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.addCleanup(port.close)

        arbitrary = 2**16 + 7

        self.assertRaises(UnsupportedAddressFamily, reactor.adoptDatagramPort,
                          port.fileno(), arbitrary, DatagramProtocol())
Ejemplo n.º 24
0
    def check(self, first=False):
        try:
            import subprocess, os, sys, time

            R = reactor.listenUDP(self._port.protocol.port, DatagramProtocol())
            R.stopListening()

            log.info('Starting repeater')
            subprocess.Popen([sys.executable, "-m", "cac.repeater"],
                             close_fds=True)

            reactor.callLater(0.5, self._port.protocol.sendReg)
        except CannotListenError:
            if first:
                self._port.protocol.sendReg()
Ejemplo n.º 25
0
    def test_invalidDescriptor(self):
        """
        An implementation of L{IReactorSocket.adoptDatagramPort} raises
        L{socket.error} if passed an integer which is not associated with a
        socket.
        """
        reactor = self.buildReactor()

        probe = socket.socket()
        fileno = probe.fileno()
        probe.close()

        exc = self.assertRaises(socket.error, reactor.adoptDatagramPort,
                                fileno, socket.AF_INET, DatagramProtocol())
        self.assertEqual(exc.args[0], errno.EBADF)
Ejemplo n.º 26
0
    def recv(self, nbytes):
        """
        Receive a datagram sent to this port using the L{MemoryIOSystem} which
        created this object.

        This behaves like L{socket.socket.recv} but the data being I{sent} and
        I{received} only passes through various memory buffers managed by this
        object and L{MemoryIOSystem}.

        @see: L{socket.socket.recv}
        """
        data = self._system._openFiles[self._fileno].writeBuffer.popleft()

        datagrams = []
        receiver = DatagramProtocol()

        def capture(datagram, address):
            datagrams.append(datagram)

        receiver.datagramReceived = capture

        udp = RawUDPProtocol()
        udp.addProto(12345, receiver)

        ip = IPProtocol()
        ip.addProto(17, udp)

        mode = self._system._openFiles[self._fileno].tunnelMode
        if (mode & TunnelFlags.IFF_TAP.value):
            ether = EthernetProtocol()
            ether.addProto(0x800, ip)
            datagramReceived = ether.datagramReceived
        else:
            datagramReceived = lambda data: ip.datagramReceived(
                data, None, None, None, None)

        dataHasPI = not (mode & TunnelFlags.IFF_NO_PI.value)

        if dataHasPI:
            # datagramReceived can't handle the PI, get rid of it.
            data = data[_PI_SIZE:]

        datagramReceived(data)
        return datagrams[0][:nbytes]
Ejemplo n.º 27
0
def _get_via_connected_udp(ipaddr):
    """
	Init a UDP socket ip discovery. We do a dns query, and retreive our
	ip address from the connected udp socket.
	
	@param ipaddr: The ip address of a dns server
	@type ipaddr: a string "x.x.x.x"
	@raise RuntimeError: When the ip is a bogus ip (0.0.0.0 or alike)
	"""
    udpprot = DatagramProtocol()
    port = reactor.listenUDP(0, udpprot)
    udpprot.transport.connect(ipaddr, 7)
    localip = udpprot.transport.getHost().host
    port.stopListening()

    if is_bogus_ip(localip):
        raise RuntimeError, "Invalid IP addres returned"
    else:
        return (is_rfc1918_ip(localip), localip)
Ejemplo n.º 28
0
def get_local_ip_for(target):
    """Find out what our IP address is for use by a given target.

    @return: the IP address as a dotted-quad native string which could be used
              to connect to us. It might work for them, it might not. If
              there is no suitable address (perhaps we don't currently have an
              externally-visible interface), this will return None.
    """

    try:
        target_ipaddr = socket.gethostbyname(target)
    except socket.gaierror:
        # DNS isn't running, or somehow we encountered an error

        # note: if an interface is configured and up, but nothing is
        # connected to it, gethostbyname("A.ROOT-SERVERS.NET") will take 20
        # seconds to raise socket.gaierror . This is synchronous and occurs
        # for each node being started, so users of
        # test.common.SystemTestMixin (like test_system) will see something
        # like 120s of delay, which may be enough to hit the default trial
        # timeouts. For that reason, get_local_addresses_async() was changed
        # to default to the numerical ip address for A.ROOT-SERVERS.NET, to
        # avoid this DNS lookup. This also makes node startup fractionally
        # faster.
        return None

    try:
        udpprot = DatagramProtocol()
        port = reactor.listenUDP(0, udpprot)
        try:
            # connect() will fail if we're offline (e.g. running tests on a
            # disconnected laptop), which is fine (localip=None), but we must
            # still do port.stopListening() or we'll get a DirtyReactorError
            udpprot.transport.connect(target_ipaddr, 7)
            localip = udpprot.transport.getHost().host
            return localip
        finally:
            d = port.stopListening()
            d.addErrback(log.err)
    except (socket.error, CannotListenError):
        # no route to that host
        localip = None
    return native_str(localip)
Ejemplo n.º 29
0
    def test_connectionLostLogMessage(self):
        """
        When a connection is lost a message is logged containing an
        address identifying the port and the fact that it was closed.
        """
        loggedMessages = self.observe()
        reactor = self.buildReactor()
        p = self.getListeningPort(reactor, DatagramProtocol())
        expectedMessage = "(UDP Port %s Closed)" % (p.getHost().port, )

        def stopReactor(ignored):
            reactor.stop()

        def doStopListening():
            del loggedMessages[:]
            maybeDeferred(p.stopListening).addCallback(stopReactor)

        reactor.callWhenRunning(doStopListening)
        self.runReactor(reactor)

        self.assertEqual((expectedMessage, ), loggedMessages[0]['message'])
Ejemplo n.º 30
0
    def parser(self):
        """
        Get a function for parsing a datagram read from a I{tap} device.

        @return: A function which accepts a datagram exactly as might be read
            from a I{tap} device.  The datagram is expected to ultimately carry
            a UDP datagram.  When called, it returns a L{list} of L{tuple}s.
            Each tuple has the UDP application data as the first element and
            the sender address as the second element.
        """
        datagrams = []
        receiver = DatagramProtocol()

        def capture(*args):
            datagrams.append(args)

        receiver.datagramReceived = capture

        udp = RawUDPProtocol()
        udp.addProto(12345, receiver)

        ip = IPProtocol()
        ip.addProto(17, udp)

        ether = EthernetProtocol()
        ether.addProto(0x800, ip)

        def parser(datagram):
            # TAP devices might include a PI header.  Strip that off if we
            # expect it to be there.
            if self.pi:
                datagram = datagram[_PI_SIZE:]

            # TAP devices include ethernet framing so start parsing at the
            # ethernet layer.
            ether.datagramReceived(datagram)
            return datagrams

        return parser