How to Negate Address Condition in sshd_config Match Block for Forced Commands


2 views

When configuring SSH access control, many administrators need to enforce different behaviors based on the client's origin network. The specific requirement here involves forcing a particular command for external connections while allowing normal SSH access for LAN users.

The OpenSSH configuration file uses Match blocks with conditions like Address to apply specific settings. However, negating these conditions isn't as straightforward as one might expect:

# These attempts don't work as intended:
Match Address !192.168.1.0/24
   ForceCommand /path/to/restricted_shell

Match Address !192.168.*
   ForceCommand /path/to/restricted_shell

# This syntax causes sshd to fail:
Match !Address 192.168.*
   ForceCommand /path/to/restricted_shell

The proper way to implement this is by using multiple Match blocks with the All condition:

# First block - allow full access for LAN
Match Address 192.168.1.0/24
   # No ForceCommand means normal access

# Second block - restrict all others
Match All
   ForceCommand /path/to/restricted_shell

While not directly supported in Address conditions, you can use exclamation marks in more specific patterns:

# This works for specific IP negation
Match Address !192.168.1.5,!192.168.1.6
   ForceCommand /path/to/restricted_shell

Here's a complete example that combines both approaches:

# Global settings
Port 22
PermitRootLogin no
PasswordAuthentication no

# Allow full access for LAN
Match Address 192.168.1.0/24,10.0.0.0/8
   PermitRootLogin prohibit-password
   X11Forwarding yes

# Restrict all other connections
Match All
   ForceCommand /usr/local/bin/restricted_shell
   PermitTTY no
   X11Forwarding no
   AllowTcpForwarding no

After making changes, always test your configuration:

sudo sshd -t  # Check for syntax errors
sudo systemctl restart sshd

Test from both internal and external networks to verify the behavior matches your expectations.

When implementing forced commands:

  • Ensure the restricted shell can't be bypassed
  • Consider additional protections like two-factor authentication
  • Log all restricted access attempts
  • Regularly audit the forced command implementation

When configuring SSH server security, administrators often need to enforce different policies based on the source network. The requirement to apply a ForceCommand only for connections originating outside a specific LAN (while allowing normal access within the LAN) presents an interesting configuration challenge.

From the attempts mentioned:

# These didn't work as expected
Match Address !192.168.1.0/24
    ForceCommand /path/to/restricted_shell

Match Address !192.168.*
    ForceCommand /path/to/restricted_shell

# This caused sshd to fail
Match !Address 192.168.*
    ForceCommand /path/to/restricted_shell

To properly negate address patterns in sshd_config, you need to use the negation syntax correctly within a single Match block:

# Working solution for OpenSSH
Match Address *,!192.168.*,!10.0.*
    ForceCommand /path/to/restricted_shell

Key points to remember:

  • The comma-separated list allows multiple patterns (both positive and negative)
  • The initial wildcard (*) matches all addresses before exclusions
  • Order matters - exclusions should come after the wildcard

Here's a full example that implements this properly:

# /etc/ssh/sshd_config
# Allow full access for LAN users
Match Address 192.168.0.0/16,10.0.0.0/8
    PermitTTY yes
    X11Forwarding yes

# Restrict external users to a specific command
Match Address *,!192.168.*,!10.*
    ForceCommand /usr/local/bin/restricted-shell
    PermitTTY no
    X11Forwarding no
    AllowTcpForwarding no

Always verify your changes:

sudo sshd -t && sudo systemctl restart sshd

Test from both internal and external networks to confirm the restrictions apply correctly.

For more complex scenarios, consider:

  1. Using iptables/nftables for network-level restrictions
  2. Implementing Match LocalPort with different ports for internal/external access
  3. Combining Match Group with address conditions for user-specific policies