smoke.sh 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #!/bin/bash
  2. set -e -x
  3. set -o pipefail
  4. mkdir -p logs
  5. NETWORK="nebula-smoke"
  6. cleanup() {
  7. echo
  8. echo " *** cleanup"
  9. echo
  10. set +e
  11. if [ "$(jobs -r)" ]
  12. then
  13. docker kill lighthouse1 host2 host3 host4
  14. fi
  15. docker network rm "$NETWORK" >/dev/null 2>&1
  16. }
  17. trap cleanup EXIT
  18. # Create a dedicated smoke network with an explicit subnet (required for --ip
  19. # below). Probe a short list of candidates so a locally-used range doesn't
  20. # fail the whole test — we only need one to be free.
  21. docker network rm "$NETWORK" >/dev/null 2>&1 || true
  22. for candidate in 172.30.0.0/24 172.31.0.0/24 10.98.0.0/24 10.99.0.0/24 192.168.230.0/24; do
  23. if docker network create --subnet "$candidate" "$NETWORK" >/dev/null 2>&1; then
  24. break
  25. fi
  26. done
  27. if ! docker network inspect "$NETWORK" >/dev/null 2>&1; then
  28. echo "failed to create $NETWORK: every candidate subnet is in use" >&2
  29. exit 1
  30. fi
  31. # Derive container IPs from the network's assigned subnet. Slots: .2 lighthouse1,
  32. # .3 host2, .4 host3, .5 host4 — matches the placeholders in build.sh.
  33. SUBNET="$(docker network inspect -f '{{(index .IPAM.Config 0).Subnet}}' "$NETWORK")"
  34. PREFIX="${SUBNET%/*}"
  35. PREFIX="${PREFIX%.*}"
  36. LIGHTHOUSE_IP="$PREFIX.2"
  37. HOST2_IP="$PREFIX.3"
  38. HOST3_IP="$PREFIX.4"
  39. HOST4_IP="$PREFIX.5"
  40. if [ "$SMOKE_OVERLAY_IPV6" ]
  41. then
  42. LIGHTHOUSE_NIP="fd00:4242:0:0:0:ffff:c0a8:6401"
  43. HOST2_NIP="fd00:4242:0:0:0:ffff:c0a8:6402"
  44. HOST3_NIP="fd00:4242:0:0:0:ffff:c0a8:6403"
  45. HOST4_NIP="fd00:4242:0:0:0:ffff:c0a8:6404"
  46. else
  47. LIGHTHOUSE_NIP="192.168.100.1"
  48. HOST2_NIP="192.168.100.2"
  49. HOST3_NIP="192.168.100.3"
  50. HOST4_NIP="192.168.100.4"
  51. fi
  52. # Sed the placeholder TEST-NET-3 IPs in the host configs to the real ones.
  53. # build/lighthouse1.yml has no IPs to rewrite so it's skipped.
  54. for f in build/host2.yml build/host3.yml build/host4.yml; do
  55. sed "s|203\.0\.113\.|$PREFIX.|g" "$f" >"$f.tmp"
  56. mv "$f.tmp" "$f"
  57. done
  58. CONTAINER="nebula:${NAME:-smoke}"
  59. docker run --name lighthouse1 --rm "$CONTAINER" -config lighthouse1.yml -test
  60. docker run --name host2 --rm -v "$PWD/build/host2.yml:/nebula/host2.yml:ro" "$CONTAINER" -config host2.yml -test
  61. docker run --name host3 --rm -v "$PWD/build/host3.yml:/nebula/host3.yml:ro" "$CONTAINER" -config host3.yml -test
  62. docker run --name host4 --rm -v "$PWD/build/host4.yml:/nebula/host4.yml:ro" "$CONTAINER" -config host4.yml -test
  63. docker run --name lighthouse1 --network "$NETWORK" --ip "$LIGHTHOUSE_IP" --device /dev/net/tun:/dev/net/tun --cap-add NET_ADMIN --rm "$CONTAINER" -config lighthouse1.yml 2>&1 | tee logs/lighthouse1 | sed -u 's/^/ [lighthouse1] /' &
  64. sleep 1
  65. docker run --name host2 --network "$NETWORK" --ip "$HOST2_IP" -v "$PWD/build/host2.yml:/nebula/host2.yml:ro" --device /dev/net/tun:/dev/net/tun --cap-add NET_ADMIN --rm "$CONTAINER" -config host2.yml 2>&1 | tee logs/host2 | sed -u 's/^/ [host2] /' &
  66. sleep 1
  67. docker run --name host3 --network "$NETWORK" --ip "$HOST3_IP" -v "$PWD/build/host3.yml:/nebula/host3.yml:ro" --device /dev/net/tun:/dev/net/tun --cap-add NET_ADMIN --rm "$CONTAINER" -config host3.yml 2>&1 | tee logs/host3 | sed -u 's/^/ [host3] /' &
  68. sleep 1
  69. docker run --name host4 --network "$NETWORK" --ip "$HOST4_IP" -v "$PWD/build/host4.yml:/nebula/host4.yml:ro" --device /dev/net/tun:/dev/net/tun --cap-add NET_ADMIN --rm "$CONTAINER" -config host4.yml 2>&1 | tee logs/host4 | sed -u 's/^/ [host4] /' &
  70. sleep 1
  71. # grab tcpdump pcaps for debugging
  72. docker exec lighthouse1 tcpdump -i tun0 -q -w - -U 2>logs/lighthouse1.inside.log >logs/lighthouse1.inside.pcap &
  73. docker exec lighthouse1 tcpdump -i eth0 -q -w - -U 2>logs/lighthouse1.outside.log >logs/lighthouse1.outside.pcap &
  74. docker exec host2 tcpdump -i tun0 -q -w - -U 2>logs/host2.inside.log >logs/host2.inside.pcap &
  75. docker exec host2 tcpdump -i eth0 -q -w - -U 2>logs/host2.outside.log >logs/host2.outside.pcap &
  76. docker exec host3 tcpdump -i tun0 -q -w - -U 2>logs/host3.inside.log >logs/host3.inside.pcap &
  77. docker exec host3 tcpdump -i eth0 -q -w - -U 2>logs/host3.outside.log >logs/host3.outside.pcap &
  78. docker exec host4 tcpdump -i tun0 -q -w - -U 2>logs/host4.inside.log >logs/host4.inside.pcap &
  79. docker exec host4 tcpdump -i eth0 -q -w - -U 2>logs/host4.outside.log >logs/host4.outside.pcap &
  80. docker exec host2 ncat -nklv 2000 &
  81. docker exec host3 ncat -nklv 2000 &
  82. docker exec host4 ncat -e '/usr/bin/echo helloagainfromhost4' -nkluv 4000 &
  83. docker exec host2 ncat -e '/usr/bin/echo host2' -nkluv 3000 &
  84. docker exec host3 ncat -e '/usr/bin/echo host3' -nkluv 3000 &
  85. set +x
  86. echo
  87. echo " *** Testing ping from lighthouse1"
  88. echo
  89. set -x
  90. docker exec lighthouse1 ping -c1 $HOST2_NIP
  91. docker exec lighthouse1 ping -c1 $HOST3_NIP
  92. set +x
  93. echo
  94. echo " *** Testing ping from host2"
  95. echo
  96. set -x
  97. docker exec host2 ping -c1 $LIGHTHOUSE_NIP
  98. # Should fail because not allowed by host3 inbound firewall
  99. ! docker exec host2 ping -c1 $HOST3_NIP -w5 || exit 1
  100. set +x
  101. echo
  102. echo " *** Testing ncat from host2"
  103. echo
  104. set -x
  105. # Should fail because not allowed by host3 inbound firewall
  106. ! docker exec host2 ncat -nzv -w5 $HOST3_NIP 2000 || exit 1
  107. ! docker exec host2 ncat -nzuv -w5 $HOST3_NIP 3000 | grep -q host3 || exit 1
  108. set +x
  109. echo
  110. echo " *** Testing ping from host3"
  111. echo
  112. set -x
  113. docker exec host3 ping -c1 $LIGHTHOUSE_NIP
  114. docker exec host3 ping -c1 $HOST2_NIP
  115. set +x
  116. echo
  117. echo " *** Testing ncat from host3"
  118. echo
  119. set -x
  120. docker exec host3 ncat -nzv -w5 $HOST2_NIP 2000
  121. docker exec host3 ncat -nzuv -w5 $HOST2_NIP 3000 | grep -q host2
  122. set +x
  123. echo
  124. echo " *** Testing ping from host4"
  125. echo
  126. set -x
  127. docker exec host4 ping -c1 $LIGHTHOUSE_NIP
  128. # Should fail because not allowed by host4 outbound firewall
  129. ! docker exec host4 ping -c1 $HOST2_NIP -w5 || exit 1
  130. ! docker exec host4 ping -c1 $HOST3_NIP -w5 || exit 1
  131. set +x
  132. echo
  133. echo " *** Testing ncat from host4"
  134. echo
  135. set -x
  136. # Should fail because not allowed by host4 outbound firewall
  137. ! docker exec host4 ncat -nzv -w5 $HOST2_NIP 2000 || exit 1
  138. ! docker exec host4 ncat -nzv -w5 $HOST3_NIP 2000 || exit 1
  139. ! docker exec host4 ncat -nzuv -w5 $HOST2_NIP 3000 | grep -q host2 || exit 1
  140. ! docker exec host4 ncat -nzuv -w5 $HOST3_NIP 3000 | grep -q host3 || exit 1
  141. set +x
  142. echo
  143. echo " *** Testing conntrack"
  144. echo
  145. set -x
  146. # host4's outbound firewall only allows ICMP to the lighthouse, so host4
  147. # cannot initiate UDP to host2. Once host2 initiates a flow to host4:4000,
  148. # conntrack must let host4's listener reply on that flow. If it doesn't,
  149. # the echo back from host4 never reaches host2.
  150. docker exec host2 sh -c "(/usr/bin/echo host2; sleep 2) | ncat -nuv $HOST4_NIP 4000" | grep -q helloagainfromhost4
  151. docker exec host4 sh -c 'kill 1'
  152. docker exec host3 sh -c 'kill 1'
  153. docker exec host2 sh -c 'kill 1'
  154. docker exec lighthouse1 sh -c 'kill 1'
  155. # Wait up to 30s for all backgrounded jobs to exit rather than relying on a
  156. # fixed sleep.
  157. for _ in $(seq 1 30); do
  158. [ -z "$(jobs -r)" ] && break
  159. sleep 1
  160. done
  161. if [ "$(jobs -r)" ]
  162. then
  163. echo "nebula still running after SIGTERM sent" >&2
  164. exit 1
  165. fi