How to automatically switch ssh config based on local subnet?

前端 未结 5 1993
无人及你
无人及你 2021-02-14 15:36

When I\'m on a certain network (subnet is 10.10.11.x) I need to jump through an intermediate host to reach my destination because of destination port I can\'t change and limited

相关标签:
5条回答
  • 2021-02-14 16:07

    Instead of checking the subnet CIDR, you can check what domain suffix DHCP has given you.

    • If you're trying to use a jump box when outside the intranet, this approach is more robust than checking for IP ranges in the reserved private allocation (e.g. your home network or remote-work location uses the same block as example.com's intranet).

    • This approach is not useful if your intranet uses the same DNS suffix everywhere and you're trying to traverse subnets within the intranet. If that's your situation, use Jakuje's solution.

    Match Host web Exec "hostname -d | ! grep -q -E '^example\.com'"
        ForwardAgent yes
        ProxyCommand ssh -p 110 -q relay.example.com nc %h %p
    Host web
        HostName web.example.com
        Port 1111
    

    If you don't have a recent version of hostname that has the -d option (e.g. you're on MacOS), you can just query resolve.conf directly:

    Match Host web Exec "! grep -q -E '^\s*search[ \t]+example\.com' /etc/resolv.conf"
        ...
        ...
    
    0 讨论(0)
  • 2021-02-14 16:13

    My solution to this problem is the following:

    Host myserver
        HostName [internal IP]
        ...
        
    Match Host [internal IP] !Exec "nc -w1 -q0 %h %p < /dev/null"
        ProxyCommand ssh jumphost -W %h:%p
    

    It's important to have the Host myserver lines first, so the SSH client will know the IP address.

    In the Match expression,

    • The Host option matches on that IP. (It accepts *, so you can match to /8, /16 or /24 subnets too.)
    • The Exec option executes a netcat with a 1 second timeout to test if the SSH port is open. If not, the ProxyCommand is used.

    This is the clearest way I found to actually test if you need a jumphost or not. If your network is lagging, you can set higher timeouts, of course. See man ssh_config for more details.

    0 讨论(0)
  • 2021-02-14 16:18

    Based on the answer by Fedor Dikarev, Mike created a bash script named onsubnet:

    #!/usr/bin/env bash
    
    if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]  || [[ "$1" == "" ]] ; then
      printf "Usage:\n\tonsubnet [ --not ] partial-ip-address\n\n"
      printf "Example:\n\tonsubnet 10.10.\n\tonsubnet --not 192.168.0.\n\n"
      printf "Note:\n\tThe partial-ip-address must match starting at the first\n"
      printf "\tcharacter of the ip-address, therefore the first example\n"
      printf "\tabove will match 10.10.10.1 but not 110.10.10.1\n"
      exit 0
    fi
    
    on=0
    off=1
    if [[ "$1" == "--not" ]] ; then
      shift
      on=1
      off=0
    fi
    
    regexp="^$(sed 's/\./\\./g' <<<"$1")"
    
    if [[ "$(uname)" == "Darwin" ]] ; then
      ifconfig | fgrep 'inet ' | fgrep -v 127.0.0. | cut -d ' ' -f 2 | egrep -q "$regexp"
    else
      hostname -I | tr -s " " "\012" | fgrep -v 127.0.0. | egrep -q "$regexp"
    fi
    
    if [[ $? == 0 ]]; then 
      exit $on
    else
      exit $off
    fi
    

    Then in his .ssh/config file, he uses Match exec like Jakuje's answer:

    Match exec "onsubnet 10.10.1." host my-server
        HostName web.example.com
        Port 1111
        ForwardAgent yes
        ProxyCommand ssh -p 110 -q relay.example.com nc %h %p
    
    Match exec "onsubnet --not 10.10.1." host my-server
        HostName web.example.com
        Port 1111
    
    0 讨论(0)
  • 2021-02-14 16:24

    I'm using the following function for that:

    function ssh() {
      network=`networksetup -getairportnetwork en0 | cut -d: -f2 | tr -d [:space:]`
      if [ -n "$network" -a -f $HOME/.ssh/config.$network ]; then
        /usr/bin/ssh -F $HOME/.ssh/config.$network "$@"
      else
        /usr/bin/ssh "$@"
      fi
    }
    export -f ssh
    

    So I need a separate configuration file for each WiFi network where I want a custom solution. It works for me right now, but it's ugly. I can recommend it only as an idea, not as the best solution.

    I'd be glad to know any better solution.

    0 讨论(0)
  • 2021-02-14 16:29

    You can use Match's exec option to execute shell commands, so you can write something like this:

    Match host web exec "hostname -I | grep -qF 10.10.11."
        ForwardAgent yes
        ProxyCommand ssh -p 110 -q relay.example.com nc %h %p
    Host web
        HostName web.example.com
        Port 1111
    

    The Match option boolean logic can short-circuit, so put host first to skip the exec term for other hosts. Try ssh web -vvv to see the Match logic in action.

    0 讨论(0)
提交回复
热议问题