Comment configurer l'espace de noms de réseau Linux, qui permet à la lettre d'information de diffusion UDP

J'essaie d'utiliser

ip netns

Famille d'équipes B. Linux Pour créer un espace de noms de réseau dans lequel je peux exécuter un programme à l'aide d'une newsletter de diffusion UDP. Je n'ai pas besoin d'accès à Internet ou à une interface dans l'espace de noms root. (Mais si cela est nécessaire pour le travail, il est certainement acceptable).

Voici un exemple serveur et client sur Ruby (Testé S. Ruby 1.9.3, Mais je m'attends à ce que cela fonctionne dans d'autres versions):

#! /usr/bin/env ruby

require 'socket'

PORT = 5000

case ARGV[0]
when 'server'
soc = UDPSocket.open
begin
soc.bind('', PORT)
puts "SERVER #{Process.pid} listening on #{PORT}"
msg = soc.recv(1)
puts "SERVER got msg: #{msg}"
ensure
soc.close
end
when 'client'
soc = UDPSocket.open
begin
soc.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
puts "CLIENT sending message"
soc.send('m', 0, '<broadcast>', PORT)
ensure
soc.close
end
else
abort "usage: #{$0} {server | client}"
end

Cela crée un serveur ou un client. Le serveur écoute

0.0.0.0

interface (

soc.bind('', ...)

). Le client envoie un message à l'adresse de diffusion. (

soc.send(..., ..., '<broadcast>', ...)

).

Lorsque vous commencez dans l'espace de noms root, il semble que cela fonctionne correctement:

$ ./udp-broadcast.rb server &amp; sleep 0.5 &amp;&amp; sudo netstat --listen --udp -p | grep 5000 &amp;&amp; ./udp-broadcast.rb client
SERVER 22981 listening on 5000
udp 0 0 *:5000 *:* 22981/ruby
CLIENT sending message
SERVER got msg: m

Voici le script dans lequel j'essaie de créer un nouvel espace de noms de réseau et de lancer les mêmes commandes:

#!

set -e

NS=udp-broadcast-test
nsexec="ip netns exec $NS"

ip netns add $NS

trap "ip netns delete $NS" EXIT

$nsexec ip link set lo up

# Can loopback have a broadcast address?
# $nsexec ip link set lo broadcast 255.255.255.255
# RTNETLINK answers: Invalid argument
# $nsexec ip addr add broadcast 255.255.255.255 dev lo
# RTNETLINK answers: Invalid argument

$nsexec ip link add veth0 type veth peer name veth1
$nsexec ifconfig veth0 192.168.99.1/24 up

$nsexec ip link
$nsexec ip route
$nsexec ifconfig

timeout 2s $nsexec ./udp-broadcast.rb server &amp;
sleep 0.2
$nsexec netstat -n --udp --listen -p
timeout 2s $nsexec ./udp-broadcast.rb client
wait

Lors du démarrage, cela donne la conclusion suivante:

$ sudo ./netns.sh
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: veth1: <broadcast,multicast> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether e2:a1:c4:14:c4:5e brd ff:ff:ff:ff:ff:ff
3: veth0: <no-carrier,broadcast,multicast,up> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/ether a6:2f:84:9f:08:36 brd ff:ff:ff:ff:ff:ff
192.168.99.0/24 dev veth0 proto kernel scope link src 192.168.99.1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

veth0 Link encap:Ethernet HWaddr a6:2f:84:9f:08:36
inet addr:192.168.99.1 Bcast:192.168.99.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

SERVER 23320 listening on 5000
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:5000 0.0.0.0:* 23320/ruby
CLIENT sending message
./udp-broadcast.rb:23:in `send': Network is unreachable - sendto(2) (Errno::ENETUNREACH)
from ./udp-broadcast.rb:23:in `<main>'

Maintenant, si je change l'adresse qui écoute le serveur et que le client envoie un message à

192.168.99.1

, alors le message vient, alors je connais mon

veth0

Au moins partiellement en cours d'exécution.

Comment puis-je configurer afin que le message de diffusion a lieu? Code de serveur / Le client est extrait du code plus vaste du code et il n'est pas facile de le changer, donc la seule chose que je puisse changer, - Ceci est la configuration de mon réseau.
</main></no-carrier,broadcast,multicast,up></broadcast,multicast></loopback,up,lower_up></broadcast></broadcast>
Invité:

Alice

Confirmation de:

Ce problème particulier est résolu en ajoutant la route par défaut à

veth0

:

$nsexec ip route add default via 192.168.99.1 dev veth0

Ajoutez cette chaîne immédiatement après la ligne qui apporte

veth0

Up, et le script est exécuté avec succès.

Catherine

Confirmation de:

Eh bien, il y a un certain nombre de raisons pour lesquelles cela ne fonctionne pas.

Vous créez un couple veth, Et puis vous ne pouvez pas ajouter d'un côté à un nouvel espace de noms de réseau.

L'un des côtés de la branche n'est pas élevé.

Spécification de l'adresse de diffusion comme

255.255.255.255

Comme dans votre exemple, appelez la recherche dans la table de routage et envoyez le package d'itinéraire par défaut.

Par conséquent, vous n'utilisez pas

SO_BINDTODEVICE

Pour spécifier quelle interface vous souhaitez vraiment envoyer. Veuillez noter que cela nécessite des privilèges. root, que dans de nombreux cas n'est pas parfait.

De plus, vous n'avez pas établi de relations de routage entre l'espace de noms d'enfants et l'espace de noms des parents, de sorte qu'il ne fonctionnera même pas avec le ping direct de l'hôte.

En général, l'utilisation d'une adresse de diffusion universelle pour toute autre chose que la fourniture de services de base réseau n'est pas une bonne pratique. Vous devez utiliser l'adresse de diffusion du sous-réseau sur lequel vous vous efforcez.

J'ai tout ce que vous avez mentionné, je travaillais sur la préparation des noms d'espace réseau.

# ip netns add TEST
# ip link add veth0 type veth peer name veth1
# ip link set dev veth1 netns TEST
# ip link set dev veth0 up
# ip netns exec TEST ip link set dev veth1 up
# ip netns exec TEST ip addr add 10.10.10.10/32 dev veth1
# ip route add 10.10.10.10/32 dev veth0
# ip netns exec TEST ip route add 192.168.1.3/32 dev veth1
# ping -c1 10.10.10.10
PING 10.10.10.10 (10.10.10.10) 56(84) bytes of data.
64 bytes from 10.10.10.10: icmp_seq=1 ttl=64 time=0.202 ms

--- 10.10.10.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.202/0.202/0.202/0.000 ms

Voici le script utilisé. faire attention à

SO_BINDTODEVICE

appeler..

#!/usr/bin/python
import socket as sock
import sys, time, os

if __name__ == "__main__":
if sys.argv[1] == "server":
s = sock.socket(sock.AF_INET, sock.SOCK_DGRAM)
s.bind(('0.0.0.0', 50000))
data = s.recvfrom(50)
print "Got {0}".format(data)

elif sys.argv[1] == "client":
s = sock.socket(sock.AF_INET, sock.SOCK_DGRAM)
s.setsockopt(sock.SOL_SOCKET, sock.SO_BROADCAST, 1)
s.setsockopt(sock.SOL_SOCKET, sock.SO_BINDTODEVICE, "veth0")
s.connect(('255.255.255.255', 50000))
s.send("hello world\n")

Et puis le résultat ..

# ip netns exec TEST python test.py server &
[1] 24961
# python test.py client
Got ('hello world\n', ('192.168.1.3', 41971))

Pour répondre aux questions, connectez-vous ou registre