rtsp_forward.sh 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #!/bin/bash
  2. # ============================================================
  3. # 摄像头 RTSP 端口转发 (板子本地端口 -> 摄像头 RTSP)
  4. # 供花生壳等内网穿透映射外网访问
  5. # 用法: bash scripts/rtsp_forward.sh start|stop|status
  6. # ============================================================
  7. set -u
  8. # 映射表: "本地端口:摄像头IP" 手机APP用 rtsp://<外网域名>:<本地端口>/Streaming/Channels/101
  9. MAP=(
  10. "8551:192.168.1.121"
  11. "8552:192.168.1.122"
  12. "8553:192.168.1.123"
  13. "8554:192.168.1.124"
  14. "8555:192.168.1.125"
  15. "8556:192.168.1.126"
  16. )
  17. CAM_PORT=554
  18. start() {
  19. sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1
  20. for entry in "${MAP[@]}"; do
  21. lport="${entry%%:*}"
  22. cip="${entry##*:}"
  23. # 外部进入的流量
  24. iptables -t nat -C PREROUTING -p tcp --dport "$lport" \
  25. -j DNAT --to-destination "$cip:$CAM_PORT" 2>/dev/null || \
  26. iptables -t nat -A PREROUTING -p tcp --dport "$lport" \
  27. -j DNAT --to-destination "$cip:$CAM_PORT"
  28. # 本机自身访问
  29. iptables -t nat -C OUTPUT -p tcp --dport "$lport" \
  30. -j DNAT --to-destination "$cip:$CAM_PORT" 2>/dev/null || \
  31. iptables -t nat -A OUTPUT -p tcp --dport "$lport" \
  32. -j DNAT --to-destination "$cip:$CAM_PORT"
  33. # 回程伪装
  34. iptables -t nat -C POSTROUTING -p tcp -d "$cip" --dport "$CAM_PORT" \
  35. -j MASQUERADE 2>/dev/null || \
  36. iptables -t nat -A POSTROUTING -p tcp -d "$cip" --dport "$CAM_PORT" \
  37. -j MASQUERADE
  38. echo "[Forward] $lport -> $cip:$CAM_PORT"
  39. done
  40. echo "[Forward] 已启动 (6路 RTSP 转发)"
  41. echo "[Forward] 手机APP拉流: rtsp://<花生壳域名>:<外网端口>/Streaming/Channels/101"
  42. echo "[Forward] 注意: 必须用 TCP 模式 (rtsp_transport=tcp), 否则RTP动态端口无法穿透"
  43. }
  44. stop() {
  45. for entry in "${MAP[@]}"; do
  46. lport="${entry%%:*}"
  47. cip="${entry##*:}"
  48. iptables -t nat -D PREROUTING -p tcp --dport "$lport" \
  49. -j DNAT --to-destination "$cip:$CAM_PORT" 2>/dev/null
  50. iptables -t nat -D OUTPUT -p tcp --dport "$lport" \
  51. -j DNAT --to-destination "$cip:$CAM_PORT" 2>/dev/null
  52. iptables -t nat -D POSTROUTING -p tcp -d "$cip" --dport "$CAM_PORT" \
  53. -j MASQUERADE 2>/dev/null
  54. echo "[Forward] 移除 $lport"
  55. done
  56. echo "[Forward] 已停止"
  57. }
  58. status() {
  59. echo "=== 端口转发规则 ==="
  60. iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep -E "dpt:(855[0-9])" || echo "(无)"
  61. echo "=== 转发连通性 (用本机实际IP, 回环不走NAT) ==="
  62. local myip
  63. myip=$(ip -4 addr show eth0 2>/dev/null | grep -oP 'inet \K[\d.]+' | head -1)
  64. myip="${myip:-127.0.0.1}"
  65. for entry in "${MAP[@]}"; do
  66. lport="${entry%%:*}"
  67. cip="${entry##*:}"
  68. # RTSP端口连通即认为正常(用timeout连socket)
  69. if timeout 2 bash -c "exec 3<>/dev/tcp/$myip/$lport" 2>/dev/null; then
  70. echo " $myip:$lport -> $cip:$CAM_PORT OK"
  71. else
  72. echo " $myip:$lport -> $cip:$CAM_PORT 失败"
  73. fi
  74. done
  75. }
  76. case "${1:-}" in
  77. start) start ;;
  78. stop) stop ;;
  79. status) status ;;
  80. *) echo "用法: $0 start|stop|status"; exit 1 ;;
  81. esac