Huawei Cloud WAF Security Event Log Analysis
Overview
This skill provides read-only analysis of Huawei Cloud WAF (Web Application Firewall) security event logs. It queries attack event data through hcloud CLI, performs multi-dimensional aggregation and analysis, and generates actionable protection rule recommendations based on observed attack patterns.
Key Capabilities:
- Query and filter security events by attack type, source IP, target domain/URL, time range, and geography
- Aggregate statistics by attack category, source IP frequency, geographic distribution, and time trends
- Recommend specific WAF protection rules (precise access control, CC protection, IP blacklist/whitelist, geo-blocking) based on analyzed attack characteristics
Applicable Scenarios:
- Daily security patrol and attack posture review
- Incident response after receiving WAF alerts
- Periodic security reports (weekly/monthly attack trends)
- Anomaly investigation when suspicious activity is detected
- Protection hardening decisions after attack events
⚠️ Read-Only Principle — STRICTLY ENFORCED
This skill is a READ-ONLY analysis skill. The agent must follow these rules without exception:
| Action | Allowed? | Explanation |
|---|---|---|
Query events (ListEvent, ShowEvent) | ✅ YES | Read-only data retrieval |
Query policies/hosts (ListPolicy, ShowPolicy, ListHost) | ✅ YES | Read-only data retrieval |
| Aggregate and analyze event data | ✅ YES | Core analysis work |
| Output recommended hcloud commands | ✅ YES | Provide copy-paste ready commands for the user |
Execute Create* / Update* / Delete* commands | ❌ NEVER | These modify production resources; the user decides when and whether to run them |
| Auto-execute any write operation based on analysis findings | ❌ NEVER | Even if the recommendation seems obvious, do NOT run it |
What the agent MUST do:
- Perform read-only queries and analysis
- Generate a structured report with prioritized recommendations
- For each recommendation, output the exact, copy-paste ready hcloud command that the user can execute themselves
- Clearly label each command with its purpose and expected effect
What the agent MUST NOT do:
- Execute any command that creates, modifies, or deletes WAF resources
- Ask the user "should I execute this for you?" — just present the command and let the user decide
- Proceed to execute recommendations after presenting them — stop after the report is delivered
Prerequisites
| Requirement | Description |
|---|---|
| hcloud CLI | v7.2+ installed and configured with AK/SK, region, and project ID |
| Project ID | Valid project ID (configured via hcloud configure set --cli-project-id=<id>) |
| IAM Permissions | See references/iam-policies.md for least-privilege policy |
| Network | Accessible network path to Huawei Cloud API endpoints |
⚠️ Windows PowerShell Compatibility — STRICTLY ENFORCED
This skill runs on Windows PowerShell. The agent MUST NOT use Linux/Unix shell commands. Use PowerShell-native equivalents at all times.
| ❌ Linux command (NEVER use) | ✅ PowerShell equivalent | Example |
|---|---|---|
head -N | Select-Object -First N | ... | Select-Object -First 30 |
tail -N | Select-Object -Last N | ... | Select-Object -Last 30 |
grep "pattern" | Select-String "pattern" | ... | Select-String "error" |
wc -l | (... ).Count or (Measure-Object -Line).Lines | $items.Count |
sort | Sort-Object | ... | Sort-Object Count -Descending |
uniq | Get-Unique or Group-Object | ... | Group-Object |
awk '{print $1}' | ForEach-Object { $_.field } | $items | ForEach-Object { $_.sip } |
cut -d: -f1 | Split-Path, -split, or Substring | ($_ -split ':')[0] |
sed 's/a/b/' | -replace operator | 'text' -replace 'a','b' |
cat file | Get-Content file | Get-Content "$env:TEMP\data.json" -Raw |
echo "text" | Write-Host "text" | Write-Host "Processing..." |
export VAR=value | $env:VAR="value" | $env:HTTP_PROXY="http://127.0.0.1:3128" |
sleep N | Start-Sleep -Seconds N | Start-Sleep -Seconds 2 |
Additional rules:
- Always use
Out-File -Encoding utf8instead of> filefor redirecting output (avoids encoding issues) - Use double quotes
"around variable expansions inside strings:"Total: $($items.Count)" - Pipe hcloud JSON output to
ConvertFrom-Jsonfor structured analysis:hcloud WAF ListEvent ... \| ConvertFrom-Json
Workflow
Step 1: Clarify Analysis Scope
Ask the user for the following parameters (defaults provided):
| Parameter | Default | Options |
|---|---|---|
| Time range | today | today, yesterday, 3days, 1week, 1month |
| Domain filter | All domains | Specific domain name or leave empty |
| Attack type filter | All types | sqli, xss, cc, botm, cmdi, robot, etc. |
| Analysis focus | General overview | Attack type stats, IP analysis, target analysis, time trends, rule recommendation |
| Data volume | First page (100) | See options below |
Data Volume Options:
| Option | Description | When to use |
|---|---|---|
first_page (default) | Query first 100 events only, fastest | Quick glance at recent activity |
sample_pages | Query N pages of events; N must be explicitly specified by the user — agent has NO default | Balanced speed vs coverage |
all_pages | Paginate through ALL results up to 10,000 | Comprehensive analysis, may take several minutes |
by_attack_type | First query to discover attack types, then query top N types separately (each gets its own first page) | Best attack-type diversity, avoids single-type bias |
⚠️ IMPORTANT — Data Volume Selection (STRICTLY ENFORCED):
- The agent MUST ask the user which data volume option to use. Do NOT silently default to any option.
- If user chooses
sample_pages, the agent MUST ask the user how many pages (N) to fetch. There is NO default value for N. The agent must NOT assume or default to any number (e.g., 5). Ask explicitly: "你想采样多少页?(每页100条事件)"- If total events > 100 and user chose
first_page, warn them that the sample may not represent the full picture.
Step 2: Query Security Events
Step 2a: Get Total Count First
Always start with a single lightweight query to determine total event count:
hcloud WAF ListEvent --recent={time_range} --pagesize=1 --page=1
Read the total field from the response. This tells you how much data exists before committing to a fetching strategy.
Step 2b: Fetch Data Based on User's Choice
Based on the user's data volume selection, execute the corresponding strategy:
Strategy: first_page (default)
Fetch one page of 100 events:
hcloud WAF ListEvent --recent={time_range} --pagesize=100 --page=1 --sort_key=attack
Save result to file:
hcloud WAF ListEvent --recent={time_range} --pagesize=100 --page=1 --sort_key=attack | Out-File -Encoding utf8 "$env:TEMP\waf_events.json"
If total > 100, display a warning to the user:
"Total events: {total}. This analysis is based on 100 events (1%). Results may not represent the full picture."
Strategy: sample_pages (user specifies N)
Loop through N pages, appending each page's items to a combined file:
$pages = {N} # e.g., 5
for ($p = 1; $p -le $pages; $p++) {
hcloud WAF ListEvent --recent={time_range} --pagesize=100 --page=$p --sort_key=attack | Out-File -Encoding utf8 "$env:TEMP\waf_events_page$p.json"
}
# Merge all pages into one file for unified analysis
$allItems = @()
for ($p = 1; $p -le $pages; $p++) {
$raw = Get-Content "$env:TEMP\waf_events_page$p.json" -Raw
$data = $raw | ConvertFrom-Json
$allItems += $data.items
}
$merged = @{ total = $data.total; items = $allItems } | ConvertTo-Json -Depth 10
$merged | Out-File -Encoding utf8 "$env:TEMP\waf_events_all.json"
Write-Host "Merged $($allItems.Count) events from $pages pages"
Strategy: all_pages
Keep paginating until all events are fetched or 10,000 cap reached:
$allItems = @()
$page = 1
$total = 0
do {
$raw = hcloud WAF ListEvent --recent={time_range} --pagesize=100 --page=$page --sort_key=attack
$data = $raw | ConvertFrom-Json
$total = $data.total
$allItems += $data.items
Write-Host "Fetched page $page / $([math]::Ceiling($total / 100)) ($($allItems.Count) / $total events)"
$page++
} while ($data.items.Count -eq 100 -and $allItems.Count -lt 10000)
$merged = @{ total = $total; items = $allItems } | ConvertTo-Json -Depth 10
$merged | Out-File -Encoding utf8 "$env:TEMP\waf_events_all.json"
Write-Host "Total fetched: $($allItems.Count) events"
⚠️ With 10,000 events this requires ~100 API calls and may take 5-10 minutes. Consider using
by_attack_typeinstead for faster diverse coverage.
Strategy: by_attack_type
Step 1 — Discover attack types by querying first page sorted by attack:
$raw = hcloud WAF ListEvent --recent={time_range} --pagesize=100 --page=1 --sort_key=attack
$data = $raw | ConvertFrom-Json
$attackTypes = $data.items | Group-Object attack | Sort-Object Count -Descending
$attackTypes | ForEach-Object { Write-Host ("{0,-30} {1}" -f $_.Name, $_.Count) }
Step 2 — For the top N attack types discovered (default N=5), query each separately:
foreach ($atk in $attackTypes | Select-Object -First {N}) {
$type = $atk.Name
hcloud WAF ListEvent --recent={time_range} --attacks.1=$type --pagesize=100 --page=1 | Out-File -Encoding utf8 "$env:TEMP\waf_events_attack_$type.json"
Write-Host "Fetched 100 events for attack type: $type"
}
Step 3 — Merge all per-type files into one combined dataset:
# Clean up old attack type files to avoid mixing with previous runs
Remove-Item "$env:TEMP\waf_events_attack_*.json" -ErrorAction SilentlyContinue
$allItems = @()
foreach ($file in Get-ChildItem "$env:TEMP\waf_events_attack_*.json") {
$raw = Get-Content $file.FullName -Raw
$data = $raw | ConvertFrom-Json
if ($data.items) { $allItems += $data.items }
}
$merged = @{ total = "multi-type-sample"; items = $allItems } | ConvertTo-Json -Depth 10
$merged | Out-File -Encoding utf8 "$env:TEMP\waf_events_all.json"
Write-Host "Combined dataset: $($allItems.Count) events across multiple attack types"
Common Query Examples
# Filter by source IP
hcloud WAF ListEvent --recent={time_range} --sip={source_ip} --pagesize=100
# ⚠️ WARNING: --domain conflicts with KooCLI system parameter and will prompt interactively
# DO NOT use --domain in automated scripts; see workaround below
# hcloud WAF ListEvent --recent={time_range} --domain={domain} --pagesize=100
# Sort by different dimensions
hcloud WAF ListEvent --recent={time_range} --sort_key=sort_ip --pagesize=100
hcloud WAF ListEvent --recent={time_range} --sort_key=attack --pagesize=100
⚠️ --domain Parameter Conflict: The
--domainparameter name conflicts with KooCLI's system parameter. Using it directly triggers an interactive prompt asking to choose between system/API parameter, which hangs non-interactive environments (e.g., Bash tool, automation scripts).Solution — Use
--cli-jsonInputto bypass the conflict:# Step 1: Create a JSON file with query parameters $jsonContent = @' { "path": { "project_id": "{project_id}" }, "query": { "recent": "today", "domain": "{domain}", "pagesize": 100, "page": 1 } } '@ $jsonContent | Out-File -FilePath "$env:TEMP\listevent_domain.json" -Encoding ASCII # Step 2: Execute with --cli-jsonInput hcloud WAF ListEvent --cli-jsonInput="$env:TEMP\listevent_domain.json" | Out-File -Encoding utf8 "$env:TEMP\domain_result.json" # Step 3: Parse result (skip hcloud's warning message) $raw = Get-Content "$env:TEMP\domain_result.json" -Raw $jsonStart = $raw.IndexOf('{') $data = $raw.Substring($jsonStart) | ConvertFrom-Json Write-Host "Filtered $($data.items.Count) events for domain: {domain}"Note:
project_idcan be obtained fromhcloud configure listor from previous API responses. hcloud outputs a warning message before JSON when using--cli-jsonInput, so use file redirect and skip to the first{character when parsing.
Important:
- Maximum 10,000 records per query; narrow time range if exceeded
--pagesizeparameter: Valid range is [0, total_data]. Default to 100 if user doesn't specify. Use user's value when provided. If API returns errorWAF.00011011: pageOrPageSize.illegal, inform the user that their pagesize value is too large and ask them to enter a smaller value within the valid range- Paginate through results if total count > pagesize (use multiple queries with
--page=1,--page=2, etc.) - Use
--fromand--to(millisecond timestamps) for custom time ranges (max 30 days) - Always save multi-page results to a merged file before analysis to avoid PowerShell variable scope issues
Step 3: Multi-Dimensional Analysis
⚠️ PowerShell Variable Scope Warning: Each Bash tool invocation runs in an isolated session — variables do NOT persist across calls. You MUST either:
- Load and analyze data in the same command block, OR
- Save query results to a file first, then reload from file in subsequent analysis commands
# ❌ WRONG - Variables don't persist across Bash calls
# Call 1: $items = hcloud WAF ListEvent ... | ConvertFrom-Json
# Call 2: $items | Group-Object attack # ERROR: $items is empty!
# ✅ CORRECT Option 1 - Single command block
$items = (hcloud WAF ListEvent --recent=today --pagesize=100 --page=1).items | ConvertFrom-Json
$items | Group-Object attack | Sort-Object Count -Descending | Select-Object Count, Name
# ✅ CORRECT Option 2 - Save to file, reload later
# Call 1: hcloud WAF ListEvent ... | Out-File -Encoding utf8 "$env:TEMP\waf_events.json"
# Call 2: $items = (Get-Content "$env:TEMP\waf_events.json" -Raw | ConvertFrom-Json).items
# $items | Group-Object attack
Aggregate the queried events across the following dimensions:
3a. Attack Type Distribution
Count events by attack field. Map attack codes to human-readable names:
| Code | Name | Recommended Rule Type |
|---|---|---|
sqli | SQL Injection | CreateCustomRule / UpdatePolicy --options.webattack=true |
xss | XSS Attack | CreateCustomRule / UpdatePolicy --options.webattack=true |
cc | CC Attack | CreateCcRule |
botm | BOT Attack | CreateAnticrawlerRule (需先调用 UpdateAnticrawlerRuleType) / UpdatePolicy --options.bot_enable=true + enable specific detectors: crawler_scanner, crawler_script, crawler_engine, crawler_other |
cmdi | Command Injection | CreateCustomRule / UpdatePolicy --options.webattack=true |
rfi | Remote File Inclusion | CreateCustomRule / UpdatePolicy --options.webattack=true |
rce | Remote Code Execution | CreateCustomRule / UpdatePolicy --options.webattack=true |
lfi | Local File Inclusion | CreateCustomRule / UpdatePolicy --options.webattack=true |
ptr | Directory Traversal | CreateCustomRule (match ../ payload) / UpdatePolicy --options.webattack=true |
robot | Malicious Crawler | CreateAnticrawlerRule (需先调用 UpdateAnticrawlerRuleType) / UpdatePolicy --options.bot_enable=true + --options.crawler_scanner=true + --options.crawler_script=true + --options.crawler_engine=true + --options.crawler_other=true |
webshell | Webshell | UpdatePolicy --options.webshell=true / CreateCustomRule |
vuln | Other Vulnerability | UpdatePolicy --options.webattack=true / CreateCustomRule |
custom_whiteblackip | IP Blacklist/Whitelist | Already using CreateWhiteblackipRule |
custom_geoip | Geo Access Control | Already using CreateGeoipRule |
custom_custom | Precise Protection | Already using CreateCustomRule |
iprank | IP Reputation | CreateIpReputationRule |
antiscan_high_freq_scan | High-frequency Scan | CreateCcRule / UpdatePolicy --options.modulex_enabled=true --modulex_options.global_rate_enabled=true |
antitamper | Anti-tamper | CreateAntiTamperRule + UpdatePolicy --options.antitamper=true |
anticrawler | Anti-crawler | CreateAnticrawlerRule + UpdatePolicy --options.anticrawler=true |
followed_action | Attack Punishment | CreatePunishmentRule + UpdatePolicy --options.followed_action=true |
antileakage | Sensitive Data Leakage | CreateAntileakageRule + UpdatePolicy --options.antileakage=true |
custom_robot | Scanner Crawler | CreateCustomRule (User-Agent matching) / CreateAnticrawlerRule |
advanced_bot | Advanced BOT | UpdatePolicy --options.bot_enable=true + CreateAnticrawlerRule |
3b. Source IP Analysis
Group by sip (source IP) field, sorted by frequency:
- Identify top attacking IPs (>5 hits in analysis period)
- Cross-reference with
ip_countriesandip_regionsfor geographic distribution - Flag IPs from unexpected countries
3c. Target Asset Analysis
Group by host (domain) and url fields:
- Identify most-targeted domains
- Identify most-targeted URL paths
- Correlate attack types with specific URLs
3d. Time Trend Analysis
The time field in API responses is a Unix millisecond timestamp (e.g., 1789696805000). It MUST be converted using [DateTimeOffset]::FromUnixTimeMilliseconds():
# CORRECT - Convert Unix millisecond timestamp to local time
$items | ForEach-Object {
[DateTimeOffset]::FromUnixTimeMilliseconds([long]$_.time).LocalDateTime.ToString("yyyy-MM-dd HH")
} | Group-Object | Sort-Object Name | Select-Object Count, Name
# WRONG - FromFileTimeUtc expects Windows FILETIME (epoch 1601-01-01),
# passing a Unix timestamp will produce dates around year 1601
[DateTime]::FromFileTimeUtc($_.time)
Aggregate the converted timestamps by hour:
- Identify peak attack periods
- Determine if attacks are sustained or burst-type
- Compare with normal traffic baseline if available
3e. Action Distribution
Group by action field (protection action taken):
- Count events by action type:
block,pass,log,captcha,cache,mask,js_challenge,advanced_captcha,abort_response,desensitize - Calculate block rate vs pass rate to assess protection effectiveness
- Identify rules that are in "log only" mode and should be escalated to "block"
Step 4: View Detailed Events (if needed)
For deeper investigation of specific events:
hcloud WAF ShowEvent --eventid={event_id}
The detail view includes: full request headers, payload content, matched rule ID, and action taken.
⚠️ Timeout Warning:
ShowEventmay fail with[USE_ERROR]调用API超时if:
- The event is old and data retrieval is slow
- The API endpoint is under heavy load
Troubleshooting steps:
- Increase read timeout:
hcloud configure set --cli-read-timeout=60- Try a more recent event ID (older events may have been archived)
- If timeout persists, the detailed event data can often be found in the original
ListEventresponse'sresponse_body,headers, and other fields — use that as a fallback
Step 5: Generate Protection Rule Recommendations
Based on the analysis results, recommend specific WAF protection rules with executable hcloud commands. See references/rule-recommendation-guide.md for detailed mapping logic and full command reference.
Quick Reference — Attack Pattern → Rule Recommendation → hcloud Command:
| Observed Pattern | Recommended Action | Rule Type |
|---|---|---|
| High-volume requests from single IP to same URL | CC protection rule (rate limiting by IP + URL) | CreateCcRule |
| SQL injection attempts targeting specific URL | Precise access control rule (URL contains + block sqli payload pattern) | CreateCustomRule |
| Attacks from specific country IPs | Geo access control rule (block specific countries) | CreateGeoipRule |
| Repeated attacks from known malicious IPs | IP blacklist rule | CreateWhiteblackipRule |
| BOT/scanner user-agent patterns | Precise access control rule (User-Agent matching) | CreateCustomRule |
| Attacks on admin/api paths | Precise access control rule (URL path restriction) | CreateCustomRule |
| Multiple attack types from same IP subnet | IP group blacklist rule | CreateWhiteblackipRule |
Malicious crawler/scanner traffic (robot) | JS anti-crawler rule (User-Agent matching) | CreateAnticrawlerRule |
IDC datacenter malicious IP (iprank) | IP reputation rule (threat intelligence) | CreateIpReputationRule |
Web content tampering (antitamper) | Anti-tamper rule (URL protection) | CreateAntiTamperRule |
Persistent attacker blocking (followed_action) | Punishment rule (auto-block after threshold) | CreatePunishmentRule |
| Sensitive data in responses | Anti-leakage rule (filter phone/id_card/email) | CreateAntileakageRule |
Webshell upload/access (webshell) | Enable webshell detection module | UpdatePolicy --options.webshell=true |
Directory traversal (ptr) / Other vuln (vuln) | Enable basic protection + custom rule for payload | UpdatePolicy --options.webattack=true |
High-frequency scan (antiscan_high_freq_scan) | CC protection or modulex scan protection | CreateCcRule / UpdatePolicy |
After determining the recommendation, output the corresponding hcloud command as a code block for the user to copy and execute themselves. Do NOT execute the command. Use the policy_id extracted from the event data (the policyid field). See below for command templates per pattern:
5a. IP Blacklist — Block Malicious Source IP
hcloud WAF CreateWhiteblackipRule --policy_id={policy_id} \
--name={rule_name} \
--addr={source_ip} \
--white=0
Parameters:
--white=0→ blacklist (block),--white=1→ whitelist (allow),--white=2→ log only--addrsupports single IP or CIDR (e.g.,203.0.113.0/24)- Verify:
hcloud WAF ListWhiteblackipRule --policy_id={policy_id} --page=1 --pagesize=10
5b. CC Protection — Rate Limiting
⚠️
--modeconflicts with KooCLI system parameter. Must use--cli-jsonInput.
Create a temporary JSON file (e.g., cc-rule.json):
{
"path": {
"project_id": "{project_id}",
"policy_id": "{policy_id}"
},
"query": {},
"body": {
"name": "{rule_name}",
"mode": 1,
"tag_type": "ip",
"limit_num": 100,
"limit_period": 60,
"lock_time": 300,
"action": {
"category": "block"
}
}
}
Note: {project_id} is the same one configured in hcloud CLI (via hcloud configure set --cli-project-id=<id>). Check current value with hcloud configure list.
Then execute:
hcloud WAF CreateCcRule --cli-jsonInput=cc-rule.json
Parameters:
tag_type:ip(by source IP),url(by URL path),cookie(by cookie),header(by header)limit_num/limit_period: threshold count within time window (seconds)lock_time: block duration (seconds) after threshold exceededaction.category:block,captcha,redirect- Verify:
hcloud WAF ListCcRules --policy_id={policy_id}
5c. Precise Access Control — Custom Rule
hcloud WAF CreateCustomRule --policy_id={policy_id} \
--name={rule_name} \
--action.category=block \
--conditions.1.category={field_category} \
--conditions.1.logic_operation={logic_op} \
--conditions.1.contents.1={match_value} \
--priority=50 \
--time=false
Common condition configurations:
| Scenario | category | index (if needed) | logic_operation | contents.1 |
|---|---|---|---|---|
| Match URL path | url | — | contain | /admin |
| Match User-Agent | user-agent | — | contain | python-requests |
| Match Header value | header | X-Custom-Header | equal | malicious-value |
| Match Cookie | cookie | session_id | contain | value |
| Match IP source | ip | — | equal | 203.0.113.1 |
| Match request method | method | — | equal | POST |
| Match payload | params | — | contain | <script> |
Additional parameters:
--conditions.N.index={field_name}— Required whencategoryisheader,cookie; NOTfield--time=false— Immediate effect; do NOT use--status--priority=N— Range 0~65535, lower = higher priority- Multi-condition AND: add
--conditions.2.category=...etc. - Logic operations:
contain,not_contain,equal,not_equal,prefix,suffix,regex,none - Verify:
hcloud WAF ListCustomRules --policy_id={policy_id}
5d. Geo Access Control — Block by Country
hcloud WAF CreateGeoipRule --policy_id={policy_id} \
--name={rule_name} \
--geoip={country_code} \
--white=0
Parameters:
--geoip— ISO 3166-1 alpha-2 country code (e.g.,KP,IR,CU)--white=0→ block traffic from this country- Caution: Always confirm with user that no legitimate business traffic comes from the blocked countries before recommending geo-blocking
- Verify:
hcloud WAF ListGeoipRule --policy_id={policy_id}
5e. Update Basic Protection Policy — Change Action from Log to Block
If events show action=log for attack types that should be blocked:
# View current policy settings
hcloud WAF ShowPolicy --policy_id={policy_id}
# Change protection action to block
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--action.category=block
# Or raise protection level (1=loose, 2=medium, 3=strict)
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--level=3
Note: UpdatePolicy can also enable/disable built-in protection modules via --options.* parameters (see 5k below).
5f. Anticrawler Rule — Block Malicious Crawlers (robot / anticrawler)
⚠️ Must call
UpdateAnticrawlerRuleTypeto set protection mode before creating anticrawler rules.
# Step 1: Set anticrawler protection mode (required prerequisite)
hcloud WAF UpdateAnticrawlerRuleType --policy_id={policy_id} \
--anticrawler_type=anticrawler_except_url
# Step 2: Create anticrawler rule
hcloud WAF CreateAnticrawlerRule --policy_id={policy_id} \
--name={rule_name} \
--type=anticrawler_except_url \
--conditions.1.category=user-agent \
--conditions.1.logic_operation=contain \
--conditions.1.contents.1={scanner_signature} \
--priority=20
Parameters (verified via --help):
--anticrawler_type/--type:anticrawler_except_url(protect all paths, rule = exclusion) oranticrawler_specific_url(protect specified paths only)--conditions.N.category:urloruser-agent--conditions.N.logic_operation:contain,not_contain,equal,prefix,suffix,regular_match, etc.--priority: 0~65535, lower = higher priority- Verify:
hcloud WAF ListAnticrawlerRules --policy_id={policy_id} --page=1 --pagesize=10
5g. IP Reputation Rule — Block Malicious IP Sources (iprank)
hcloud WAF CreateIpReputationRule --policy_id={policy_id} \
--name={rule_name} \
--type=idc \
--action.category=block \
--tags.1={threat_tag}
Parameters (verified via --help):
--type: Currently only supportsidc(IDC data center IP)--action.category:block(拦截),log(仅记录),pass(放行)--tags.N: Threat intelligence tags (obtain fromListIpReputationRulesor threat intel console)- Verify:
hcloud WAF ListIpReputationRules --policy_id={policy_id} --page=1 --pagesize=10
5h. Anti-Tamper Rule — Protect Web Content (antitamper)
hcloud WAF CreateAntiTamperRule --policy_id={policy_id} \
--hostname={protected_domain} \
--url={protected_url} \
--description={rule_description}
Parameters (verified via --help):
--hostname: Protected domain (fromListHostresponsehostnamefield)--url: Protected URL path, e.g.,/admin/index.htmlor/static/*(*suffix = prefix match)--description: Optional rule description- Verify:
hcloud WAF ListAntitamperRule --policy_id={policy_id} --page=1 --pagesize=10 - Note: Must also enable the module:
hcloud WAF UpdatePolicy --policy_id={policy_id} --options.antitamper=true
5i. Punishment Rule — Block Persistent Attackers (followed_action)
hcloud WAF CreatePunishmentRule --policy_id={policy_id} \
--category={punishment_category} \
--block_time={block_seconds} \
--time_unit={time_unit} \
--description={rule_description}
Parameters (verified via --help):
--category: One of:short_ip_block/short_cookie_block/short_params_block/short_header_block— short-term punishmentlong_ip_block/long_cookie_block/long_params_block/long_header_block— long-term punishment
--block_time: Block duration (range depends on category and time_unit):short_*+SECOND: [1, 300]long_*+SECOND: [301, 7776000]long_*+MINUTE: [6, 129600]long_*+HOUR: [1, 2160]long_*+DAY: [1, 90]long_*+MONTH: [1, 3]
--time_unit:SECOND(default),MINUTE,HOUR,DAY,MONTH- Note: Each category can only have one rule; category cannot be modified after creation
- Verify:
hcloud WAF ListPunishmentRules --policy_id={policy_id} - Note: Must also enable the module:
hcloud WAF UpdatePolicy --policy_id={policy_id} --options.followed_action=true
5j. Anti-Leakage Rule — Prevent Sensitive Data Exposure
hcloud WAF CreateAntileakageRule --policy_id={policy_id} \
--category={category} \
--contents.1={content_value} \
--url={protected_url} \
--action.category=block \
--description={rule_description}
Parameters (verified via --help):
--category:code(HTTP status code) orsensitive(sensitive information)--contents.N:- For
code: HTTP status codes —400,401,402,403,404,405,500,501,502,503,504,507 - For
sensitive:phone(phone number),id_card(ID card),email
- For
--url: URL path to apply the rule--action.category:block(filter) orlog(record only)- Verify:
hcloud WAF ListAntileakageRules --policy_id={policy_id} --page=1 --pagesize=10 - Note: Must also enable the module:
hcloud WAF UpdatePolicy --policy_id={policy_id} --options.antileakage=true
5k. Enable/Disable Built-in Protection Modules
Use UpdatePolicy with --options.* to toggle built-in protection modules:
# View current module status
hcloud WAF ShowPolicy --policy_id={policy_id}
# Enable webshell detection
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.webshell=true
# Enable anti-tamper module
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.antitamper=true
# Enable anticrawler module
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.anticrawler=true
# Enable attack punishment module
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.followed_action=true
# Enable anti-leakage module
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.antileakage=true
# Enable scanner detection (crawler_scanner)
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.crawler_scanner=true
# Enable script crawler detection
hcloud WAF UpdatePolicy --policy_id={policy_id} \
--options.crawler_script=true
Full list of --options.* parameters (verified via UpdatePolicy --help):
| Parameter | Description |
|---|---|
--options.webattack | Basic web protection (sqli, xss, cmdi, lfi, rfi, vuln) |
--options.webshell | Webshell detection |
--options.cc | CC protection rules |
--options.custom | Precise access control |
--options.whiteblackip | IP blacklist/whitelist |
--options.geoip | Geo access control |
--options.antitamper | Anti-tamper |
--options.anticrawler | Anti-crawler (JS challenge) |
--options.antileakage | Anti-leakage (sensitive data) |
--options.followed_action | Attack punishment |
--options.privacy | Privacy masking |
--options.ignore | Global whitelist (false positive bypass) |
--options.crawler_scanner | Scanner detection |
--options.crawler_script | Script crawler detection |
--options.crawler_engine | Search engine crawler |
--options.crawler_other | Other crawler detection |
--options.bot_enable | BOT management master switch |
--options.modulex_enabled | Intelligent CC (modulex, beta) |
5l. Enable/Disable Single Rule by Status
Toggle individual rules on/off without deleting them:
hcloud WAF UpdatePolicyRuleStatus --policy_id={policy_id} \
--rule_id={rule_id} \
--rule_type={rule_type} \
--status={0|1}
Parameters (verified via --help):
--rule_type:cc,custom,whiteblackip,geoip,ip-reputation,antitamper,antileakage,ignore,privacy--status:0= disable,1= enable- Note: Useful for temporary rule disabling during troubleshooting
KooCLI Parameter Pitfalls
| Pitfall | ❌ Wrong | ✅ Correct |
|---|---|---|
| Nested params | --action=block | --action.category=block |
| Header field name | --conditions.1.field=UA | --conditions.1.index=User-Agent |
| Immediate effect | --status=1 | --time=false |
| mode conflict | --mode=1 (direct) | --cli-jsonInput=file.json |
| Array index | --conditions.0.xxx | --conditions.1.xxx (starts from 1) |
| Singular/plural | ListWhiteblackipRules | ListWhiteblackipRule |
| Case sensitivity | ShowWhiteblackipRule | ShowWhiteBlackIpRule (capital B) |
Step 6: Present Analysis Report
Output a structured report containing:
- Summary — Total events, time range, top findings
- Attack Type Breakdown — Counts and percentages
- Top Attacking IPs — With geographic info
- Most Targeted Assets — Domains and URLs
- Time Distribution — Peak periods
- Recommended Rules — Prioritized list with copy-paste ready hcloud commands (DO NOT execute them)
Report Delivery Format:
## 🛡️ Protection Recommendations
### Priority 1: [Rule Name]
**Purpose**: [What this rule does]
**Expected Effect**: [Impact on security posture]
**Command to execute** (copy and run in your terminal):
```bash
hcloud WAF CreateXxxRule --policy_id={policy_id} ...
Verification command (after you execute the above):
hcloud WAF ListXxxRule --policy_id={policy_id}
**Important**: After presenting the report with all recommended commands, **STOP**. Do not ask "should I execute these?" or attempt to run them. The user will decide when and whether to execute the commands.
## Core Commands
| Command | Purpose |
|---------|---------|
| `hcloud WAF ListEvent` | Query attack event list with multi-dimensional filtering, sorting, and pagination |
| `hcloud WAF ShowEvent` | View detailed information of a single attack event |
| `hcloud WAF ListAttackActionTypes --from=<ms_timestamp> --to=<ms_timestamp>` | Aggregate event counts by protection action type (block/log/pass/etc.) within the specified time range |
### ListEvent Key Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `--recent` | string | Quick time range: `today`, `yesterday`, `3days`, `1week`, `1month` |
| `--from` / `--to` | integer | Custom time range (millisecond timestamps), max 30 days |
| `--attacks.N` | array | Filter by attack type: `sqli`, `xss`, `cc`, `botm`, `cmdi`, `rfi`, `rce`, `lfi`, `ptr`, `webshell`, `vuln`, `robot`, `iprank`, `antitamper`, `anticrawler`, `followed_action`, `antileakage`, `antiscan_high_freq_scan`, `custom_whiteblackip`, `custom_geoip`, `custom_custom`, `advanced_bot`, etc. Run `ListAttackActionTypes` for full list |
| `--actions.N` | array | Filter by action: `block`, `pass`, `log`, `captcha`, `cache`, `mask`, `js_challenge`, `advanced_captcha`, `abort_response`, `desensitize` |
| `--sip` | string | Filter by source IP (supports fuzzy match with `--query_mode=include`) |
| `--sips.N` | array | Filter by multiple source IPs |
| `--domain` | string | Filter by domain (fuzzy match) |
| `--url` | string | Filter by URL (supports fuzzy match with `--query_mode=include`) |
| `--urls.N` | array | Filter by URL list |
| `--query_mode` | string | Query mode: `equal` (exact match) or `include` (fuzzy match, default). Affects `--sip` and `--url` only |
| `--ip_countries.N` | array | Filter by client IP country |
| `--ip_regions.N` | array | Filter by client IP province (China only) |
| `--rules.N` | array | Filter by matched rule ID |
| `--sort_key` | string | Sort field: `attack_time`, `sort_ip`, `host`, `geo_str`, `component`, `rule`, `attack` |
| `--sort_direction` | string | `desc` (default) or `asc` |
| `--page` / `--pagesize` | integer | Pagination controls |
| `--payload` | string | Search by malicious payload content |
| `--nattacks.N` | array | Exclude attack type (opposite of `--attacks.N`) |
| `--enterprise_project_id` | string | Enterprise project filter |
## Parameter Confirmation
| Parameter | Required | Description | Example |
|-----------|----------|-------------|---------|
| `{time_range}` | No | Analysis time window (default: `today`) | `1week` |
| `{domain}` | No | Target domain filter | `example.com` |
| `{attack_type}` | No | Attack type filter | `sqli` |
| `{source_ip}` | No | Source IP filter | `203.0.113.1` |
## Reference Documents
- `references/iam-policies.md` — Least-privilege IAM policies for WAF log querying
- `references/cli-installation-guide.md` — hcloud CLI installation and configuration
- `references/verification-method.md` — How to verify the skill is working correctly
- `references/dataflow-diagram.md` — Mermaid data flow diagram
- `references/acceptance-criteria.md` — Acceptance criteria for analysis output quality
- `references/rule-recommendation-guide.md` — Detailed attack-to-rule mapping logic
## KooCLI Command Format Standard
```bash
hcloud <Service> <Operation> [--key=value ...]
| Feature | Description | Example |
|---|---|---|
| Service name | Exact KooCLI service name, uppercase | WAF |
| Operation name | PascalCase | ListEvent, ShowEvent |
| Simple parameter | --key=value | --sip=203.0.113.1 |
| Indexed parameter | --key.N=value | --attacks.1=sqli --attacks.2=xss |
| Region | Use default configured region; do NOT specify --cli-region | hcloud WAF ListEvent --recent=today |