惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
小众软件
小众软件
Last Week in AI
Last Week in AI
月光博客
月光博客
博客园 - 聂微东
Recent Announcements
Recent Announcements
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
博客园 - Franky
云风的 BLOG
云风的 BLOG
量子位
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
博客园 - 司徒正美
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享

dgl.cx

SSH port knocking with OpenBSD 7.9 Bash a newline: Exploiting SSH via ProxyCommand, again (CVE-2025-61984) Switchable dark mode with 5 lines of JavaScript Images over DNS CVE-2025-48384: Breaking Git with a carriage return and cloning RCE Can your terminal do emojis? How big? Blink and you'll miss it — a URL handler surprise Using HAProxy to protect me from scrapers Déjà vu: Ghostly CVEs in my terminal title Restrict sftp with Linux user namespaces ""?! ANSI Terminal security in 2023 and finding 10 CVEs NAT-Again: IRC NAT helper flaws ip.wtf and showing you your actual HTTP request
SSH port knocking with OpenBSD 7.9
2026-06-18 · via dgl.cx

Port knocking is mostly a bad idea. But people keep wanting to do it, for some false sense of security. If you don't consider it a security control but a way to keep garbage out of your logs, it might be valid. In my case I'm using an old USG Pro 4 running OpenBSD as my firewall and I'd prefer to avoid writing stuff to the logs, as I'd prefer the flash not to wear out sooner than needed, definitely not thanks to background radiation on the internet.

Here is a pf.conf fragment using the OpenBSD 7.9 source limiter feature:

# Chosen by fair dice roll
knock1 = "24601"
knock2 = "29202"

# no need for knocking for these hosts
table <good-hosts> persist {
  192.0.2.0/24 # replace with whatever you trust
}

table <stage1-passed> persist {}
table <stage2-passed> persist {}
table <bad-hosts> persist {}

source limiter "stage1" id 1 entries 1000 \
  limit 2 rate 10/100 \
  table <stage1-passed> above 1

source limiter "stage2" id 2 entries 1000 \
  limit 2 rate 10/100 \
  table <stage2-passed> above 1

source limiter "bad" id 3 entries 10000 \
  limit 2 rate 10/100 \
  table <bad-hosts> above 1

# ssh port knocking
anchor to self {
  pass in quick proto tcp from {<good-hosts> <stage2-passed>} to port {>= 1024, 22}
  block return-rst in quick proto tcp from <bad-hosts>
  block return-rst in quick proto tcp to port 22
  pass in quick proto tcp to port $knock1 source limiter "stage1" (no-match)
  pass in quick proto tcp from <stage1-passed> to port $knock2 source limiter "stage2" (no-match)
  # source limiter needs a "pass" rule, ensure you have rules to block access
  # to ports >= 1024 you need to protect.
  pass in proto tcp to port >= 1024 source limiter "bad" (no-match)
  block return-rst proto tcp to port >= 1024
}

Once this was configured, I had no more ssh brute force attempts in the logs:

$ zgrep 'Jun  2' /var/log/* 2>/dev/null
       9

Ah, peaceful 🧘‍♂️

Using return-rst means that it is harder to observe when the host has been blocked, essentially turning the source limiter into a thing which does not block anything but instead sets state.

Configuring the ssh client

To get into this you need to hit the source limiter twice, for each port. We can use OpenSSH's Match tagged keyword to make this nicer.

Add something like this to the end of ~/.ssh/config:

Match Final Tagged knock Exec "telnet %h 24601; telnet %h 24601; telnet %h 29202; telnet %h 29202; true"

Then use it with ssh -P knock your-host. You should see 4 connection refused lines from telnet, then your SSH connection.

Alternatively rather than using -P knock, you can use the LocalNetwork match to make this happen automatically depending which network you are on.

Match Final LocalNetwork !10.x.y.0/24 Host *.domain Exec "telnet %h 24601; telnet %h 24601; telnet %h 29202; telnet %h 29202; true"

(Unfortunately because of the ssh config parser that has to be on one line.)

The limits are arranged so a host is more likely to get blocked than accidentally find the ports, even via scanning. However this shouldn't be treated as a security control, it's mostly a way to stop clogging the logs with scans, without having to run yet another daemon to do it.

18th June 2026