説明なし

send-wazuh-fortigate-continuous.sh 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. PROFILE="${1:-mixed}"
  4. MODELS="${2:-all}"
  5. BASE_DELAY="${3:-0.8}"
  6. WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
  7. WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
  8. SIM_MAX_EVENTS="${SIM_MAX_EVENTS:-0}" # 0 = run forever
  9. SIM_SRC_PREFIX="${SIM_SRC_PREFIX:-10.10.20}"
  10. SIM_VPN_USER="${SIM_VPN_USER:-remote.user}"
  11. SIM_ADMIN_USER="${SIM_ADMIN_USER:-admin}"
  12. EVENT_COUNT=0
  13. if ! [[ "${BASE_DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
  14. echo "error: base delay must be numeric (e.g. 0.8)"
  15. exit 1
  16. fi
  17. if ! [[ "${SIM_MAX_EVENTS}" =~ ^[0-9]+$ ]]; then
  18. echo "error: SIM_MAX_EVENTS must be an integer >= 0"
  19. exit 1
  20. fi
  21. emit_syslog() {
  22. local msg="$1"
  23. local sent="false"
  24. if command -v nc >/dev/null 2>&1; then
  25. if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
  26. sent="true"
  27. fi
  28. fi
  29. if [[ "${sent}" != "true" ]]; then
  30. if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
  31. sent="true"
  32. fi
  33. fi
  34. if [[ "${sent}" != "true" ]]; then
  35. echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
  36. return 1
  37. fi
  38. EVENT_COUNT=$((EVENT_COUNT + 1))
  39. echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent(${EVENT_COUNT}): ${msg}"
  40. }
  41. pick_model() {
  42. case "${MODELS}" in
  43. 501E|501e) echo "501E" ;;
  44. 80F|80f) echo "80F" ;;
  45. 60F|60f) echo "60F" ;;
  46. 40F|40f) echo "40F" ;;
  47. all)
  48. case $((RANDOM % 4)) in
  49. 0) echo "501E" ;;
  50. 1) echo "80F" ;;
  51. 2) echo "60F" ;;
  52. *) echo "40F" ;;
  53. esac
  54. ;;
  55. *)
  56. echo "error: unknown models '${MODELS}'"
  57. echo "valid: 501E | 80F | 60F | 40F | all"
  58. exit 1
  59. ;;
  60. esac
  61. }
  62. devname_for_model() {
  63. case "$1" in
  64. 501E) echo "FGT501E-HQ" ;;
  65. 80F) echo "FGT80F-Branch01" ;;
  66. 60F) echo "FGT60F-Store12" ;;
  67. 40F) echo "FGT40F-SMB01" ;;
  68. *) echo "FGT-UNKNOWN" ;;
  69. esac
  70. }
  71. devid_for_model() {
  72. case "$1" in
  73. 501E) echo "FGT501E12345678" ;;
  74. 80F) echo "FGT80FTK20000001" ;;
  75. 60F) echo "FGT60FTK21001234" ;;
  76. 40F) echo "FGT40FTK22004567" ;;
  77. *) echo "FGT00000000000000" ;;
  78. esac
  79. }
  80. src_ip() {
  81. echo "${SIM_SRC_PREFIX}.$((RANDOM % 220 + 10))"
  82. }
  83. event_ts() {
  84. echo "$(date +%s)"
  85. }
  86. syslog_prefix() {
  87. local pri="$1"
  88. local model="$2"
  89. local devname
  90. local devid
  91. devname="$(devname_for_model "${model}")"
  92. devid="$(devid_for_model "${model}")"
  93. printf "<%s>date=%s time=%s devname=\"%s\" devid=\"%s\" eventtime=%s vd=\"root\"" \
  94. "${pri}" "$(date '+%Y-%m-%d')" "$(date '+%H:%M:%S')" "${devname}" "${devid}" "$(event_ts)"
  95. }
  96. send_traffic_allow() {
  97. local model="$1"
  98. local sip
  99. sip="$(src_ip)"
  100. emit_syslog "$(syslog_prefix 189 "${model}") logid=\"0000000013\" type=\"traffic\" subtype=\"forward\" level=\"notice\" srcip=${sip} srcport=$((RANDOM % 40000 + 1024)) srcintf=\"lan\" dstip=172.217.14.$((RANDOM % 200 + 20)) dstport=443 dstintf=\"wan1\" proto=6 service=\"HTTPS\" policyid=12 action=\"accept\" sentbyte=$((RANDOM % 4000 + 500)) rcvdbyte=$((RANDOM % 20000 + 1000)) duration=$((RANDOM % 60 + 2)) soc_mvp_test=true vendor=fortinet product=fortigate model=${model} event_type=fortigate_traffic_allow severity=low"
  101. }
  102. send_webfilter_block() {
  103. local model="$1"
  104. local sip
  105. sip="$(src_ip)"
  106. emit_syslog "$(syslog_prefix 190 "${model}") logid=\"0419016384\" type=\"utm\" subtype=\"webfilter\" level=\"warning\" srcip=${sip} srcintf=\"internal\" dstip=104.18.$((RANDOM % 200 + 1)).$((RANDOM % 240 + 10)) dstport=80 hostname=\"suspicious-$((RANDOM % 9000 + 1000)).example\" url=\"/dropper\" action=\"blocked\" cat=52 profile=\"WF-Strict\" policyid=3 soc_mvp_test=true vendor=fortinet product=fortigate model=${model} event_type=fortigate_webfilter_block severity=medium"
  107. }
  108. send_ips_block() {
  109. local model="$1"
  110. local sip
  111. sip="$(src_ip)"
  112. emit_syslog "$(syslog_prefix 190 "${model}") logid=\"0720018432\" type=\"utm\" subtype=\"ips\" level=\"alert\" srcip=${sip} dstip=45.155.$((RANDOM % 200 + 1)).$((RANDOM % 240 + 10)) srcport=$((RANDOM % 40000 + 1024)) dstport=445 sessionid=$((RANDOM % 9000000 + 1000000)) action=\"blocked\" attack=\"MS.SMB.Server.Service.Remote.Code.Execution\" severity=\"critical\" policyid=8 soc_mvp_test=true vendor=fortinet product=fortigate model=${model} event_type=fortigate_ips_block severity=high"
  113. }
  114. send_vpn_down() {
  115. local model="$1"
  116. emit_syslog "$(syslog_prefix 191 "${model}") logid=\"0104044546\" type=\"event\" subtype=\"vpn\" level=\"warning\" user=\"${SIM_VPN_USER}\" tunneltype=\"ipsec\" remip=203.0.113.$((RANDOM % 200 + 10)) locip=198.51.100.$((RANDOM % 200 + 10)) action=\"tunnel-down\" reason=\"peer-not-responding\" msg=\"IPsec tunnel Branch-HQ is down\" soc_mvp_test=true vendor=fortinet product=fortigate model=${model} event_type=fortigate_vpn_down severity=high"
  117. }
  118. send_admin_login() {
  119. local model="$1"
  120. emit_syslog "$(syslog_prefix 191 "${model}") logid=\"0100032002\" type=\"event\" subtype=\"system\" level=\"information\" logdesc=\"Admin login successful\" user=\"${SIM_ADMIN_USER}\" ui=\"https(10.20.1.$((RANDOM % 200 + 10)))\" msg=\"Administrator ${SIM_ADMIN_USER} logged in successfully\" soc_mvp_test=true vendor=fortinet product=fortigate model=${model} event_type=fortigate_admin_login severity=low"
  121. }
  122. send_event_by_profile() {
  123. local model="$1"
  124. local roll
  125. roll=$((RANDOM % 100))
  126. case "${PROFILE}" in
  127. normal)
  128. if [[ "${roll}" -lt 80 ]]; then
  129. send_traffic_allow "${model}"
  130. elif [[ "${roll}" -lt 92 ]]; then
  131. send_admin_login "${model}"
  132. elif [[ "${roll}" -lt 98 ]]; then
  133. send_webfilter_block "${model}"
  134. else
  135. send_vpn_down "${model}"
  136. fi
  137. ;;
  138. incident)
  139. if [[ "${roll}" -lt 45 ]]; then
  140. send_traffic_allow "${model}"
  141. elif [[ "${roll}" -lt 70 ]]; then
  142. send_webfilter_block "${model}"
  143. elif [[ "${roll}" -lt 92 ]]; then
  144. send_ips_block "${model}"
  145. else
  146. send_vpn_down "${model}"
  147. fi
  148. ;;
  149. mixed)
  150. if [[ "${roll}" -lt 65 ]]; then
  151. send_traffic_allow "${model}"
  152. elif [[ "${roll}" -lt 82 ]]; then
  153. send_webfilter_block "${model}"
  154. elif [[ "${roll}" -lt 94 ]]; then
  155. send_admin_login "${model}"
  156. elif [[ "${roll}" -lt 98 ]]; then
  157. send_vpn_down "${model}"
  158. else
  159. send_ips_block "${model}"
  160. fi
  161. ;;
  162. *)
  163. echo "error: unknown profile '${PROFILE}'"
  164. echo "valid: normal | incident | mixed"
  165. exit 1
  166. ;;
  167. esac
  168. }
  169. echo "starting FortiGate continuous simulator"
  170. echo "profile=${PROFILE} models=${MODELS} base_delay=${BASE_DELAY}s target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp max_events=${SIM_MAX_EVENTS}"
  171. echo "press Ctrl+C to stop"
  172. trap 'echo; echo "stopped after ${EVENT_COUNT} events"; exit 0' INT TERM
  173. while true; do
  174. send_event_by_profile "$(pick_model)"
  175. if [[ "${SIM_MAX_EVENTS}" -gt 0 && "${EVENT_COUNT}" -ge "${SIM_MAX_EVENTS}" ]]; then
  176. echo "done: reached SIM_MAX_EVENTS=${SIM_MAX_EVENTS}"
  177. exit 0
  178. fi
  179. # occasional burst to mimic short real-world spikes
  180. if [[ $((RANDOM % 100)) -lt 12 ]]; then
  181. send_event_by_profile "$(pick_model)"
  182. [[ "${SIM_MAX_EVENTS}" -gt 0 && "${EVENT_COUNT}" -ge "${SIM_MAX_EVENTS}" ]] && exit 0
  183. send_event_by_profile "$(pick_model)"
  184. [[ "${SIM_MAX_EVENTS}" -gt 0 && "${EVENT_COUNT}" -ge "${SIM_MAX_EVENTS}" ]] && exit 0
  185. fi
  186. sleep "${BASE_DELAY}"
  187. done