knockd(1)

πŸ“¦
version 0.8 Β· 3 versions
, in debian bookworm, debian trixie, ubuntu jammy, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ knockd β€” the port-knock server bestie πŸ’…

okay so real quick, this page is knockd(1) β€” like, the manual page for knockd itself, section 1. she's the server side of the port-knocking operation. let's get into it 🫢


🌸 NAME 🌸

knockd β€” she's a port-knock server. that's it, that's the whole name, iconic behavior honestly πŸ’–


🌈 SYNOPSIS 🌈

knockd [options]

πŸ’– DESCRIPTION πŸ’–

okay so listen. knockd is a port-knock server. she parks herself on an ethernet (or PPP) interface and just... watches everything. all the traffic. all of it. πŸ‘€ she's looking for special "knock" sequences of port-hits, like a secret handshake but for ports.

a client does these port-hits by yeeting a TCP (or UDP) packet at a port on the server. and here's the slay part β€” that port does NOT need to be open. because knockd is listening down at the link-layer level, she sees all the traffic even if it's destined for a closed port. she's not like other servers. she sees everything πŸ’…

when she detects a specific sequence of port-hits, she runs a command defined in her config file. and what's that for? opening up holes in your firewall for quick access, bestie. it's giving ✨discreet✨


πŸ‘‘ COMMANDLINE OPTIONS πŸ‘‘

  • -i, --interface <int> β€” pick which interface she listens on. the default is eth0. classic.
  • -d, --daemon β€” become a daemon. this is usually what you want for normal server-like operation, like a real grown-up service 🧚
  • -c, --config <file> β€” point her at a different config file. default is /etc/knockd.conf.
  • -D, --debug β€” output debugging messages. when you need to see what she's thinking 🫢
  • -l, --lookup β€” lookup DNS names for log entries. this may be a security risk!! go read the SECURITY NOTES section, i'm serious 😭
  • -4, --only-ip-v4 β€” ignore packets from IPv6, handle only IPv4.
  • -v, --verbose β€” output verbose status messages. chatty era.
  • -V, --version β€” display the version.
  • -h, --help β€” syntax help. we love a helpful queen.

πŸŽ€ CONFIGURATION πŸŽ€

knockd reads all her knock/event sets from a configuration file. every knock/event kicks off with a title marker, formatted like [name], where name is the name of the event that'll show up in the log. and there's one special marker, [options], used to define global options. periodt.

🌟 Example #1 🌟

this one uses two knocks. the first lets the knocker access port 22 (SSH), and the second closes the port once the knocker is done. as you can see, this could be useful if you run a very restrictive (DENY policy) firewall and would like to access it discreetly. lowkey genius.

[options]
     logfile = /var/log/knockd.log

[openSSH]
     sequence    = 7000,8000,9000
     seq_timeout = 10
     tcpflags    = syn
     command     = /sbin/iptables -A INPUT -s %IP% --dport 22 -j ACCEPT

[closeSSH]
     sequence    = 9000,8000,7000
     seq_timeout = 10
     tcpflags    = syn
     command     = /sbin/iptables -D INPUT -s %IP% --dport 22 -j ACCEPT

🌟 Example #2 🌟

this one uses a single knock to control access to port 22 (SSH). after receiving a successful knock, the daemon will run the start_command, wait for the time specified in cmd_timeout, then execute the stop_command. super useful to automatically close the door behind a knocker πŸšͺ✨ the knock sequence uses both UDP and TCP ports.

[options]
     logfile = /var/log/knockd.log

[opencloseSSH]
     sequence      = 2222:udp,3333:tcp,4444:udp
     seq_timeout   = 15
     tcpflags      = syn,ack
     start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --syn -j ACCEPT
     cmd_timeout   = 5
     stop_command  = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --syn -j ACCEPT

🌟 Example #3 🌟

this one doesn't use a single, fixed knock sequence to trigger an event β€” instead it uses a set of sequences taken from a sequence file (one time sequences), specified by the one_time_sequences directive. after each successful knock, the used sequence gets invalidated and the next sequence from the sequence file has to be used for a successful knock. this prevents an attacker from doing a replay attack after having discovered a sequence (eg, while sniffing the network). not me being protected πŸ›‘οΈ

[options]
     logfile = /var/log/knockd.log

[opencloseSMTP]
     one_time_sequences = /etc/knockd/smtp_sequences
     seq_timeout        = 15
     tcpflags           = fin,!ack
     start_command      = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 25 -j ACCEPT
     cmd_timeout        = 5
     stop_command       = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 25 -j ACCEPT

🌟 Example #4 🌟

example to support IPv4 and IPv6. you can provide a dedicated command for each of the two protocols. dual-stack queen πŸ’œ

[options]
     logfile = /var/log/knockd.log

[opencloseSMTP]
     one_time_sequences = /etc/knockd/smtp_sequences
     seq_timeout        = 15
     tcpflags           = fin,!ack
     start_command      = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 25 -j ACCEPT
     start_command_6    = /usr/sbin/ip6tables -A INPUT -s %IP% -p tcp --dport 25 -j ACCEPT
     cmd_timeout        = 5
     stop_command       = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 25 -j ACCEPT
     stop_command_6     = /usr/sbin/ip6tables -D INPUT -s %IP% -p tcp --dport 25 -j ACCEPT

πŸ¦‹ CONFIGURATION: GLOBAL DIRECTIVES πŸ¦‹

these are the big-picture, everybody's-included settings bestie 🌈

  • UseSyslog β€” log action messages through syslog(). this will insert log entries into your /var/log/messages or equivalent.
  • LogFile = /path/to/file β€” log actions directly to a file, usually /var/log/knockd.log.
  • PidFile = /path/to/file β€” pidfile to use when in daemon mode, default: /var/run/knockd.pid.
  • Interface = <interface_name> β€” network interface to listen on. only its name has to be given, not the path to the device (eg, "eth0" and not "/dev/eth0"). default: eth0.

🌸 CONFIGURATION: KNOCK/EVENT DIRECTIVES 🌸

now the per-event stuff. this is where the magic happens ✨

  • Sequence = <port1>[:<tcp|udp>],<port2>[:<tcp|udp>][,<port3>[:<tcp|udp>] ...] β€” specify the sequence of ports in the special knock. if a wrong port with the same flags is received, the knock is discarded. optionally, you can define the protocol to be used on a per-port basis (default is TCP).
  • One_Time_Sequences = /path/to/one_time_sequences_file β€” file containing the one time sequences to be used. instead of using a fixed sequence, knockd will read the sequence to be used from that file. after each successful knock attempt this sequence will be disabled by writing a '#' character at the first position of the line containing the used sequence. that used sequence will then be replaced by the next valid sequence from the file.

because the first character is replaced by a '#', it is recommended that you leave a space at the beginning of each line. otherwise the first digit in your knock sequence will be overwritten with a '#' after it has been used. 😭 don't let that be you.

each line in the one time sequences file contains exactly one sequence and has the same format as the one for the Sequence directive. lines beginning with a '#' character will be ignored.

Note: Do not edit the file while knockd is running! like, seriously, hands off 🫢
  • Seq_Timeout = <timeout> β€” time to wait for a sequence to complete, in seconds. if the time elapses before the knock is complete, it is discarded.
  • TCPFlags = fin|syn|rst|psh|ack|urg β€” only pay attention to packets that have this flag set. when using TCP flags, knockd will IGNORE tcp packets that don't match the flags. this is different than the normal behavior, where an incorrect packet would invalidate the entire knock, forcing the client to start over. using "TCPFlags = syn" is useful if you are testing over an SSH connection, as the SSH traffic will usually interfere with (and thus invalidate) the knock. πŸ™ˆ

separate multiple flags with commas (eg, TCPFlags = syn,ack,urg). flags can be explicitly excluded by a "!" (eg, TCPFlags = syn,!ack).

  • Target = <ip-address> β€” use the specified IP address instead of the address determined for the Interface when matching the Sequence. this is useful if knockd is running on a router and you want to do something in response to an actual connection attempt to a routed host β€” e.g., invoking etherwake to send the host a WOL packet. πŸŒ™
  • Start_Command = <command> β€” specify the command to be executed when a client makes the correct port-knock with IPv4. all instances of %IP% will be replaced with the knocker's IP address. the Command directive is an alias for Start_Command.
  • Start_Command_6 = <command> β€” specify the command to be executed when a client makes the correct port-knock with IPv6. all instances of %IP% will be replaced with the knocker's IP address. the Command_6 directive is an alias for Start_Command_6. if not present it will automatically fallback onto the same IPV4 Start_Command value. you can use an empty value to force doing nothing.
  • Cmd_Timeout = <timeout> β€” time to wait (in seconds) between Start_Command and Stop_Command. this directive is optional, only required if Stop_Command is used.
  • Stop_Command = <command> β€” specify the command to be executed when Cmd_Timeout seconds have passed since Start_Command has been executed. all instances of %IP% will be replaced with the knocker's IP address. this directive is optional.
  • Stop_Command_6 = <command> β€” specify the command to be executed when Cmd_Timeout seconds have passed since Start_Command_6 has been executed. all instances of %IP% will be replaced with the knocker's IP address. this directive is optional. if not present it will automatically fallback onto the same IPV4 Stop_Command value. you can use an empty value to force doing nothing.

πŸ”₯ SECURITY NOTES πŸ”₯

Using the -l or --lookup commandline option to resolve DNS names for log entries may be a security risk!! 😭

an attacker may find out the first port of a sequence if he can monitor the DNS traffic of the host running knockd. also, a host supposed to be stealth (eg, dropping packets to closed TCP ports instead of replying with an ACK+RST packet) may give itself away by resolving a DNS name if an attacker manages to hit the first (unknown) port of a sequence.

like... she's supposed to be invisible bestie, don't blow her cover πŸ’€


πŸ’œ SEE ALSO πŸ’œ

knock is the accompanying port-knock client, though telnet or netcat could be used for simple TCP knocks instead. for more advanced knocks, see hping, sendip or packit. go off, little tools πŸ¦‹


⭐ AUTHOR ⭐

Judd Vinet <jvinet@zeroflux.org>


and that's the whole vibe check πŸ’… this was knockd 0.8, dated April 22, 2021 β€” so yeah, if you were looking for the page info: version 0.8, dated April 22, 2021, from the knockd(1) manual. slay, bye bestie 🫢✨