Prioritize interactive SSH with PF

ToS


When SSH is used for an interactive login session, the ToS-field in the IP-headers will be set to “minimize delay” (0×10), PF can use this information to place the packets in a different queue. SFTP and SCP will set the ToS to “maximize throughput” (0×8) and when SSH are being used as a transport for other protocols, such as CVS or Rsync, no ToS-value will be set at all.


tcpdump1 output from an interactive login session.


0.0.0.0.27859 > 0.0.0.0.22: tcp 0 (DF) [tos 0x10] (ttl 64, id 8913, len 52)


Output from an SFTP file transfer, notice the different ToS-value.


0.0.0.0.8321 > 0.0.0.0.22: tcp 1448 (DF) [tos 0x8] (ttl 64, id 19794, len 1500)


PF


When using the queue keyword in PF, one or two queues can be specified. If the second queue is specified, it will be used for packets with the ToS-header set to “minimize delay” or if it is being used in conjunction with “keep state”, the ACK packets will be assign to that queue.


In my ruleset, I use this rule to assign the interactive SSH to another queue, with a higher priority.


pass out on $ext_if $tcp to port ssh flags S/SA queue (std_out, ssh_out)


With this I can use SCP and SFTP without having to worry about chocking other traffic.


One thing I have noticed is that the first few packets being sent when starting an SSH-connection will not have the ToS-field set. So the SSH-initiation could be a bit “slow” when you’re upstream bandwidth is full. I don’t know how to solve this yet, though I don’t think it cause any major pain.


Another thing I’ve just noticed is that when I’m downloading through SCP/SFTP, the ACK packets are put in the wrong queue, they’re in the ssh_out-queue but I want them in the ack_out-queue. Have to ponder that one a bit more.


Here’s my complete ruleset.


Footnote


1 The -tvqn parameters were given to tcpdump(8)