USB 네트워크 연결에서 TFTP를 사용하여 플래시(공장)된 장치를 사용합니다.
서버에는 고정된 192.168.2.100 주소가 있고 장치에는 고정된 192.168.2.101 주소가 있습니다. 시작되면 펌웨어 다운로드를 위해 연결됩니다.
현재 설정에서는 동시에 하나의 장치만 작동할 수 있습니다. 하지만 저는 연결할 수 있는 만큼 많은 장치를 플래시할 수 있도록 하고 싶습니다(엄청난 플래시 요구 사항이 있을 수 있기 때문입니다).
라우팅 문제를 우회하기 위해 나는 setockopt를 SO_BIND_DEVICE로 설정하는 xinetd 버전을 만들었습니다.
하지만 제가 예외로 삼지 않은 점은 Linux가 두 인터페이스 모두에서 동시에 ARP 요청을 처리할 수 없다는 것입니다.
"ping 192.168.2.101 -I usb0"과 "ping 192.168.2.101 -I usb1"을 동시에 수행하면 하나의 인터페이스에서 작동합니다.
ARP, Request who-has sk tell 192.168.2.100, length 28
ARP, Reply 192.168.2.101 is-at 7a:0f:66:7c:fc:2c (oui Unknown), length 28
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 21807, seq 1, length 64
IP 192.168.2.101 > 192.168.2.100: ICMP echo reply, id 21807, seq 1, length 64
그러나 다른 한편으로는 그렇지 않습니다:
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31071, seq 1, length 64
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31071, seq 2, length 64
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31077, seq 1, length 64
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
서버가 ARP 요청에 응답하지 않는 것 같습니다.
다음은 /etc/network/if-up.d/000-first 스크립트를 사용하여 서버에서 장치의 연결을 처리하는 방법입니다.
ifconfig $IFACE up
ifconfig $IFACE 192.168.2.100
PID=/var/run/xinetd-$IFACE.pid
# this is the modified xinetd version to bind on one address
kill -9 `cat $PID`
xinetd -pidfile $PID -interface $IFACE
# I tried this to force the handling of ARP table per interface, but it doesn't change anything:
# /usr/sbin/arpd -b /tmp/$IFACE.db -a 3 -k $IFACE
다음은 수정된 xinetd 버전입니다: https://github.com/fcliramb/xinetd/commit/1f5c1e8f9944e372b137e6aa46247f8de807bece#L8R253
답변1
먼저, Proxy arp 자체를 시도해보지 않으셨다면, Proxy arp를 시도해 보시기 바랍니다.
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
옵션 1: 일부 connmark/policy 경로 맹글링
프록시 arp만으로는 작동하지 않는다면 이것이 작동할 것이라고 보장할 수는 없지만 시도해 볼 가치는 있다고 생각합니다. 제가 설명하려는 것은 conntrack을 사용하여 입력 인터페이스를 기반으로 응답을 바인딩하도록 정책 라우팅을 설정하는 방법입니다. 두 개의 인터페이스에 대해 설정하는 방법을 설명할 것이며 어떤 숫자로든 쉽게 확장할 수 있을 것입니다. 반면에 작동하는 대신 단순히 혼란스러워지고 아무 일도 하지 않을 수 있습니다(아마도 커널 arp 테이블이 장치당 ip/mac 쌍을 캐시해야 한다는 것을 모르기 때문일 것입니다). 그런 일이 발생하면 더 보기 흉한 두 번째 방법을 시도해 보세요.
먼저 몇 가지 connmark mangle 규칙을 설정합니다.
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT
/etc/iproute2/rt_tables에 100과 101이라는 두 개의 테이블을 추가하고 usb0과 usb1로 레이블을 지정합니다.
100 usb0
101 usb1
각 테이블에 대해 다음을 추가합니다(<N>을 적절한 숫자로 교체).
ip route add 192.168.2.0/24 dev usb<N> table usb<N>
ip rule add fw <N> table usb<N>
iptables -t mangle -A PREROUTING -i usb<N> -j MARK --set-mark <N>
확실하지는 않지만 tftp 데몬이 수신할 수 있도록 다음과 같은 더미 인터페이스를 설정해야 할 수도 있습니다.
modprobe dummy
ifconfig dummy0 192.168.2.100/32 up
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
sysctl net.ipv4.ip_forward=1
iptables -I FORWARD -s 192.168.2.100 -j ACCEPT
iptables -I FORWARD -d 192.168.2.100 -j ACCEPT
이제 두 개의 장치로 테스트해 보세요. 작동한다면 훌륭합니다. 그렇지 않으면 다음 방법을 시도해 보세요.
옵션 2: USB 네트 장치당 kvm 컨테이너
옵션 2는 일부 브리징과 qemu/kvm을 포함하여 더 추악합니다. virt-manager
아마도 이러한 것들을 만드는 가장 쉬운 방법일 것입니다.
USB 인터페이스당 하나씩 탭 장치와 브리지를 만듭니다.
tunctl -t tap<N>
brctl addbr usb<N>br
brctl addif usb<N>br tap<N>
brctl addif usb<N>br usb<N> # this may need to be done each time the usb device is connected/disconnected.
읽기 전용으로 설계된 kvm 이미지 파일이나 부팅 CD를 만들고 TFTP 서버와 이미지를 호스팅합니다... 또는 읽기 전용을 생략하고 vm당 하나의 이미지 파일을 만듭니다(이를 위해 스냅샷을 사용하는 것이 더 좋지만 더 나을 것입니다) 이 답변보다 범위가 넓습니다).
탭 인터페이스와 이미지 파일을 사용하여 kvm을 실행하고 USB 네트워크 연결을 테스트합니다.
비교
connmark/policy 경로가 작동했다면 tftp 저장소를 동기적으로 유지 관리하는 것이 훨씬 쉽습니다. KVM을 사용하면 VM 이미지당 저장소가 필요할 수 있습니다(가능한 각 VM에 읽기 전용 디렉터리를 전달하지 않는 한). Connmark/policy 경로는 좀 더 까다롭지만 하나의 tftp 서버만 필요합니다. 하지만 포트가 충분히 무작위이지 않으면 conntrack이 혼란스러워지고 포트가 겹치면 덮어쓸 수 있습니다(또는 그렇지 않을 수도 있습니다). 반면에 kvms에 브리징하려면 훨씬 더 많은 메모리가 필요합니다. 연결된 USB 장치마다 전체 VM이 있지만 VM에는 작업할 격리된 전체 네트워크 스택이 있고 호스트 커널은 브리지를 통해 패킷을 앞뒤로 전달해야 하기 때문에 매번 작동할 가능성이 훨씬 더 높습니다. 특히 브리지 필터링의 경우에는 더욱 그렇습니다. 꺼져 있습니다.
이 두 가지 중 하나가 귀하에게 도움이 되기를 바랍니다.