Математическая математика с плавающей запятой такова. В большинстве языков программирования он основан на стандарте IEEE 754 . JavaScript использует 64-битное представление с плавающей запятой, которое совпадает с Java double
. Суть проблемы состоит в том, что числа представлены в этом формате как целое число раз в два раза; рациональные числа (такие как 0.1
, который является 1/10
), знаменатель которого не является степенью двух, не могут быть точно представлены.
Для 0.1
в стандартном формате binary64
представление может записывается в точности как
0.1000000000000000055511151231257827021181583404541015625
в десятичной форме или 0x1.999999999999ap-4
в нотации C99 hexfloat . Напротив, рациональное число 0.1
, которое является 1/10
, может быть записано точно как
0.1
в десятичной форме или 0x1.99999999999999...p-4
в аналоге обозначения гексафлоата C99, где ...
представляет собой бесконечную последовательность 9. Константы 0.2
и 0.3
в вашей программе также будут приближенными к их истинные ценности. Бывает, что ближайший double
до 0.2
больше, чем рациональное число 0.2
, но ближайший double
до 0.3
меньше, чем рациональное число 0.3
. Сумма 0.1
и 0.2
заканчивается выше, чем рациональное число 0.3
и, следовательно, не согласуется с константой в вашем коде.
Достаточно полное рассмотрение арифметических вопросов с плавающей запятой Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой . Для более простого объяснения см. floating-point-gui.de .
Процитированная статья делает это довольно понятным ...
Поскольку вы не завершаете полное рукопожатие TCP, ваша операционная система может попытаться взять управление и начать отправку пакетов RST (сброс) , чтобы избежать этого, мы можем использовать iptables:
blockquote>iptables -A OUTPUT -p tcp --tcp-flags RST RST -s 192.168.1.20 -j DROP
По сути, проблема в том, что
scapy
работает в пользовательском пространстве, а ядро linux сначала получит SYN-ACK. Ядро отправит RST, потому что у него не будет открытого сокета на указанном номере порта, прежде чем вы сможете что-либо сделать с помощьюscapy
.Решение (как упоминает блог) это брандмауэр вашего ядра от отправки RST-пакета.
Статья в блоге, приведенная в других ответах, не совсем корректна. Дело не только в том, что вы не выполняете трехстороннее рукопожатие, а в том, что IP-стек ядра не знает, что происходит соединение. Когда он получает SYN-ACK
, он отправляет RST-ACK
, потому что это неожиданно. Получение первого или последнего действительно не входит в него. Стек , получающий SYN-ACK
, является проблемой.
Использование IPTables для удаления исходящих пакетов RST
- это общий и действительный подход, но иногда вам нужно отправить RST
от Scapy. Более сложный, но очень эффективный подход заключается в том, чтобы идти ниже, генерируя и реагируя на ARP с MAC, который отличается от хоста. Это позволяет вам иметь возможность отправлять и получать что угодно без каких-либо помех от хоста.
Очевидно, что это больше усилий. Лично я использую этот подход (в отличие от подхода RST
dropping), когда мне действительно нужно отправить сам RST
.
У меня нет ответа на не-iptables, но можно исправить проблему с перезагрузкой. Вместо того, чтобы пытаться отфильтровать исходящий сброс в таблице фильтров, вместо этого отфильтруйте все входящие пакеты из целевого объекта в исходной таблице. Это предотвращает передачу пакетов возврата из цели даже обработкой ядром, хотя scapy все еще видит их. Я использовал следующий синтаксис:
iptables -t raw -A PREROUTING -p tcp --dport <source port I use for scapy traffic> -j DROP
Это решение заставляет меня использовать один и тот же исходный порт для моего трафика; не стесняйтесь использовать свой собственный iptables-fu для идентификации возвращаемых пакетов вашей цели.