Сокет не будет связываться: нет такого устройства
Итак, у меня есть эта часть кода Python 3:
import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(eth_packet)
Этот код работает на моем малине Pi, но не на моем внешнем сервере. Когда я пытаюсь запустить его на моем внешнем сервере, я получаю:
# sudo python3 test.py
s.send(eth_packet)
socket.error: [Errno 19] No such device
И я проверил вывод сетевых интерфейсов (через python script):
Внешний сервер (debian):
['lo [index=1, IPv4=127.0.0.1, IPv6=::1]', 'eth0:0 [index=2, IPv4=xxxxx, IPv6=None]', 'eth0 [index=2, IPv4=yyyyyy, IPv6=zzzzzzz]']
Малина pi:
['lo [index=1, IPv4=127.0.0.1, IPv6=None]', 'eth0 [index=2, IPv4=rrrrr, IPv6=None]']
Может кто-нибудь объяснить, что происходит? Я просто хочу отправить сообщение handcrafted, но эта ошибка продолжает прослушивать меня, может это проблема с драйверами моего сервера? Это тот же результат, что и ifconfig.
Edit
Хорошо, я использовал strace для этого примера:
#!/usr/bin/env python3
import socket
import binascii
import struct
test= '000a959d6816'
packet= struct.pack("!6s", binascii.unhexlify(bytes(test, 'UTF-8')))
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(('eth0', 0))
s.send(packet)
И это важная часть о strace:
socket(PF_PACKET, SOCK_RAW, 0) = 3
ioctl(3, SIOCGIFINDEX, {ifr_name="eth0", ifr_index=2}) = 0
bind(3, {sa_family=AF_PACKET, proto=0000, if2, pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0
sendto(3, "\0\n\225\235h\26", 6, 0, NULL, 0) = -1 ENXIO (No such device or address)
open("test.py", O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff86c5f090) = -1 ENOTTY (Inappropriate ioctl for device)
fstat(4, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
lseek(4, 0, SEEK_CUR) = 0
dup(4) = 5
fcntl(5, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fstat(5, {st_mode=S_IFREG|0644, st_size=247, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc1251c2000
lseek(5, 0, SEEK_CUR) = 0
read(5, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(5) = 0
munmap(0x7fc1251c2000, 4096) = 0
lseek(4, 0, SEEK_SET) = 0
lseek(4, 0, SEEK_CUR) = 0
read(4, "#!/usr/bin/env python3\n\nimport s"..., 4096) = 247
close(4) = 0
write(2, "Traceback (most recent call last"..., 143Traceback (most recent call last):
File "test.py", line 11, in <module>
s.send(packet)
socket.error: [Errno 6] No such device or address
) = 143
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fc1264050a0}, {0x428787, [], SA_RESTORER, 0x7fc1264050a0}, 8) = 0
close(3) = 0
Ответы
Ответ 1
Когда вы связываете RAW-сокет с семейством PACKET на интерфейсе, вам нужен кортеж с двумя объектами:
(interfaceName, protoNumber)
или 5 объектов:
(interfaceName, protoNumber, pkttype, hatype, haddr)
Вы указываете 0 в protoNumber, но, возможно, protoNumber 0 не существует в вашей системе.
Документация о семействе пакетов: пакет (7)
sll_protocol - это стандартный тип протокола ethernet в сетевом байте порядок, определенный в файле include.
Попробуйте найти правильный номер протокола в linux/if_ether.h.
Ответ 2
Предполагая, что ваш внешний сервер работает под Linux, есть некоторые причины не запускать вашу программу.
Как уже отмечалось в Figus, вы фактически используете номер протокола 0, который не может быть определен. Вам может быть повезло больше:
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, proto)
где proto
- номер протокола, соответствующий ETH_P_ALL в linux/if_ether.h(3 в некоторых Linux-блоках)
Но man packet
также говорит: Только процессы с эффективным UID 0 или CAP_NET_RAW могут открывать пакетные сокеты. Таким образом, это означает, что для запуска вашего кода у вас должны быть права root на вашем внешнем сервере.
Ответ 3
это клиент, который может отправить сообщение ручной работы. переменными ip и портом являются порт и IP-адрес вашего сервера, значения в приведенной ниже программе являются примерами
import socket
ip = "127.0.0.1"
port = 447
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
msg = ("hello ex. message")
s.send(msg.encode('ascii'))
rep = s.recv(1024)
rep1 = (rep.decode('ascii'))
print rep1
и сервер
import socket
ip = "127.0.0.1"
port = 447
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((ip, port))
s.listen(15)
con, addr = s.accept()
msg = con.recv(1024)
msg1 = (msg.decode('ascii'))
print (msg1)
rep = ("got message")
con.send(rep.encode('ascii'))
Я надеюсь, что этот ответ поможет, и это то, что вы ищете.