LINUX.ORG.RU

История изменений

Исправление rtxtxtrx, (текущая версия) :

Да оно только так и работает:

def normalize_ports(ports: list[str]) -> set[int]:
    rv = set()
    for x in ports:
        try:
            a, b = map(int, x.split("-", 1))
            rv.update(range(a, b + 1))
        except ValueError:
            rv.add(int(x))
    return rv


WELL_KNOWN_PORTS = frozenset(
    [
        110,
        143,
        21,
        22,
        2222,
        23,
        25,
        3306,
        443,
        465,
        5432,
        587,
        5900,
        6379,
        80,
        8080,
        8443,
        9000,
        993,
        995,
    ]
)


class NameSpace(argparse.Namespace):
    address: str
    ports: list[str]
    debug: bool
    timeout: float


def parse_args(
    argv: list[str] | None,
) -> tuple[argparse.ArgumentParser, NameSpace]:
    parser = argparse.ArgumentParser()
    parser.add_argument("address", type=socket.gethostbyname)
    parser.add_argument(
        "-p",
        "--port",
        dest="ports",
        nargs="+",
        help="port or range of ports",
    )
    parser.add_argument("-t", "--timeout", type=float, default=15.0)
    parser.add_argument("-d", "--debug", action="store_true", default=False)
    args = parser.parse_args(argv, namespace=NameSpace())
    return parser, args


def main(argv: list[str] | None = None) -> None:
    _, args = parse_args(argv)

    if args.debug:
        logging.basicConfig()
        logger.setLevel(logging.DEBUG)

    ports = normalize_ports(args.ports) if args.ports else WELL_KNOWN_PORTS

    local_ip = get_local_ip()

    sniff_t = threading.Thread(
        target=sniff,
        args=(local_ip, args.address, ports),
    )

    sniff_t.daemon = True
    sniff_t.start()

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW
    ) as s:
        for port in ports:
            src_port = random.randint(30000, 50000)
            packet = make_syn_packet(local_ip, src_port, args.address, port)
            n = s.sendto(packet, (args.address, 0))
            logger.debug("bytes sent: %d", n)

    sniff_t.join(args.timeout)


def sniff(local_ip: str, target_ip: str, ports: set[int]) -> None:

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP
    ) as s:
        while 1:
            res, addr = s.recvfrom(65535)

            if addr[0] != target_ip:
                continue

            src_ip = socket.inet_ntoa(res[12:16])

            if src_ip != target_ip:
                continue

            dst_ip = socket.inet_ntoa(res[16:20])

            if dst_ip != local_ip:
                continue

            src_port = int.from_bytes(res[20:22])
            # dst_port = int.from_bytes(res[22:24])

            # Это самый быстрый способ проверить открыт ли порт
            if res[33] == 0x012 and src_port in ports:
                print(src_ip, src_port)


if __name__ == "__main__":
    sys.exit(main())

Так-то он нормально порты перебирает:

❯ sudo ./scan_ports.py github.com
140.82.121.3 22
140.82.121.3 443
140.82.121.3 80

Исправление rtxtxtrx, :

Да оно только так и работает:

def normalize_ports(ports: list[str]) -> set[int]:
    rv = set()
    for x in ports:
        try:
            a, b = map(int, x.split("-", 1))
            rv.update(range(a, b + 1))
        except ValueError:
            rv.add(int(x))
    return rv


WELL_KNOWN_PORTS = frozenset(
    [
        110,
        143,
        21,
        22,
        2222,
        23,
        25,
        3306,
        443,
        465,
        5432,
        587,
        5900,
        6379,
        80,
        8080,
        8443,
        9000,
        993,
        995,
    ]
)


class NameSpace(argparse.Namespace):
    address: str
    ports: list[str]
    debug: bool
    timeout: float


def parse_args(
    argv: list[str] | None,
) -> tuple[argparse.ArgumentParser, NameSpace]:
    parser = argparse.ArgumentParser()
    parser.add_argument("address", type=socket.gethostbyname)
    parser.add_argument(
        "-p",
        "--port",
        dest="ports",
        nargs="+",
        help="port or range of ports",
    )
    parser.add_argument("-t", "--timeout", type=float, default=15.0)
    parser.add_argument("-d", "--debug", action="store_true", default=False)
    args = parser.parse_args(argv, namespace=NameSpace())
    return parser, args


def main(argv: list[str] | None = None) -> None:
    _, args = parse_args(argv)

    if args.debug:
        logging.basicConfig()
        logger.setLevel(logging.DEBUG)

    ports = normalize_ports(args.ports) if args.ports else WELL_KNOWN_PORTS

    local_ip = get_local_ip()

    sniff_t = threading.Thread(
        target=sniff,
        args=(local_ip, args.address, ports),
    )

    sniff_t.daemon = True
    sniff_t.start()

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW
    ) as s:
        for port in ports:
            src_port = random.randint(30000, 50000)
            packet = make_syn_packet(local_ip, src_port, args.address, port)
            n = s.sendto(packet, (args.address, 0))
            logger.debug("bytes sent: %d", n)

    sniff_t.join(args.timeout)


def sniff(local_ip: str, target_ip: str, ports: set[int]) -> None:

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP
    ) as s:
        while 1:
            res, addr = s.recvfrom(65535)

            if addr[0] != target_ip:
                continue

            src_ip = socket.inet_ntoa(res[12:16])

            if src_ip != target_ip:
                continue

            dst_ip = socket.inet_ntoa(res[16:20])

            if dst_ip != local_ip:
                continue

            src_port = int.from_bytes(res[20:22])
            # dst_port = int.from_bytes(res[22:24])

            # Это самый быстрый способ проверить открыт ли порт
            if res[33] == 0x012 and src_port in ports:
                print(src_ip, src_port)


if __name__ == "__main__":
    sys.exit(main())

Исходная версия rtxtxtrx, :

Да оно только так и работает:

def normalize_ports(ports: list[str]) -> set[int]:
    rv = set()
    for x in ports:
        try:
            a, b = map(int, x.split("-", 1))
            rv.update(range(a, b + 1))
        except ValueError:
            rv.add(int(x))
    return rv


WELL_KNOWN_PORTS = frozenset(
    [
        110,
        143,
        21,
        22,
        2222,
        23,
        25,
        3306,
        443,
        465,
        5432,
        587,
        5900,
        6379,
        80,
        8080,
        8443,
        9000,
        993,
        995,
    ]
)


class NameSpace(argparse.Namespace):
    address: str
    ports: list[str]
    debug: bool
    timeout: float


def parse_args(
    argv: list[str] | None,
) -> tuple[argparse.ArgumentParser, NameSpace]:
    parser = argparse.ArgumentParser()
    parser.add_argument("address", type=socket.gethostbyname)
    parser.add_argument(
        "-p",
        "--port",
        dest="ports",
        nargs="+",
        help="port or range of ports",
    )
    parser.add_argument("-t", "--timeout", type=float, default=15.0)
    parser.add_argument("-d", "--debug", action="store_true", default=False)
    args = parser.parse_args(argv, namespace=NameSpace())
    return parser, args


def main(argv: list[str] | None = None) -> None:
    _, args = parse_args(argv)

    if args.debug:
        logging.basicConfig()
        logger.setLevel(logging.DEBUG)

    ports = normalize_ports(args.ports) if args.ports else WELL_KNOWN_PORTS

    local_ip = get_local_ip()

    sniff_t = threading.Thread(
        target=sniff,
        args=(local_ip, args.address, ports),
    )

    sniff_t.daemon = True
    sniff_t.start()

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW
    ) as s:
        for port in ports:
            src_port = random.randint(30000, 50000)
            packet = make_syn_packet(local_ip, src_port, args.address, port)
            s = socket.socket(
                socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW
            )
            n = s.sendto(packet, (args.address, 0))
            logger.debug("bytes sent: %d", n)

    sniff_t.join(args.timeout)


def sniff(local_ip: str, target_ip: str, ports: set[int]) -> None:

    with socket.socket(
        socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP
    ) as s:
        while 1:
            res, addr = s.recvfrom(65535)

            if addr[0] != target_ip:
                continue

            src_ip = socket.inet_ntoa(res[12:16])

            if src_ip != target_ip:
                continue

            dst_ip = socket.inet_ntoa(res[16:20])

            if dst_ip != local_ip:
                continue

            src_port = int.from_bytes(res[20:22])
            # dst_port = int.from_bytes(res[22:24])

            # Это самый быстрый способ проверить открыт ли порт
            if res[33] == 0x012 and src_port in ports:
                print(src_ip, src_port)


if __name__ == "__main__":
    sys.exit(main())