как туннелировать
Туннелирование с помощью ssh — это то, чем я всегда хотел заниматься. Отправная точка: в компании некоторые машины часто недоступны, и к ним можно получить доступ только через машину разработки, предоставленную компанией, но мы можем получить доступ к машине разработки в интрасети.
Базовые знания
SSH — это сетевой протокол, используемый для зашифрованного входа между компьютерами.
- Удаленный хост получает запрос пользователя на вход в систему и отправляет пользователю свой собственный открытый ключ.
- Пользователь использует этот открытый ключ для шифрования пароля входа и отправки его обратно.
- Удаленный хост использует свой собственный закрытый ключ для расшифровки пароля для входа.Если пароль правильный, пользователю разрешается войти в систему.
Первый шаг, который уязвим для атаки в вышеописанном процессе, — как мы узнаем, что полученный публичный ключ является реальным хостом, что отражается в фактическом входе в систему, то есть он появится:
 $ ssh user@host
  The authenticity of host 'host (12.18.429.21)' can't be established.
  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
  Are you sure you want to continue connecting (yes/no)?
здесьRSA key fingerprint
Это подпись MD5 открытого ключа 128. Если да, она будет сохранена в $HOME/.ssh/known_hosts, указывая, что открытый ключ распознан.
После решения проблемы доверия следующая плохая вещь заключается в том, что вам нужно каждый раз вводить пароль, поэтому естьлогин с открытым ключом, то есть пользователь хранит свой открытый ключ на удаленном хосте. При входе в систему удаленный хост отправляет пользователю случайную строку, а пользователь шифрует ее своим закрытым ключом и отправляет обратно. Удаленный хост выполняет расшифровку с помощью предварительно сохраненного открытого ключа. В случае успеха это доказывает, что пользователь доверенный, и разрешает вход в оболочку напрямую, не требуя пароля.
Подводя итог, можно сказать, что существует два способа аутентификации ssh:
- имя пользователя + сертификат
- имя пользователя + пароль
Давайте посмотрим на соответствующий метод работы в go.
golang реализует ssh-клиент
go get -u golang.org/x/crypto/...
Во-первых, давайте поговорим о 2 методах аутентификации, отобразить пароль, пройтиssh.Password
ввести пароль
sshConfig := &ssh.ClientConfig{
User: "your_user_name",
Auth: []ssh.AuthMethod{
ssh.Password("your_password")
},
}
Второй способ — это способ сертификата, который подразделяется на два вида: один — это чтение нашего собственного закрытого ключа напрямую, а другой — чтение из ssh-agent, который используется для помощи нам в управлении закрытыми ключами. решить проблему, заключающуюся в том, что когда мы обращаемся к разным хостам, используя разные пары закрытый ключ-открытый ключ, и решить проблему, заключающуюся в том, что если установлен пароль закрытого ключа, его необходимо каждый раз устанавливать вручную. пс: управление ssh-агентом
eval `ssh-agent` 启动agent代理
ssh-add /path/to/key/key_name 添加指定私钥
ssh-agent -k 关闭 agent
ssh-add -l 查看代理中私钥
ssh-add -L 查看代理中私钥对应的公钥
ssh-add -d /path/to/key/key_name 移除指定私钥
ssh-add -D 删除管理的所有私钥
читать из файла
func PublicKeyFile(file string) ssh.AuthMethod {
buffer, err := ioutil.ReadFile(file)
if err != nil {
return nil
}
key, err := ssh.ParsePrivateKey(buffer)
if err != nil {
return nil
}
return ssh.PublicKeys(key)
}
чтение из ssh-агента
func SSHAgent() ssh.AuthMethod {
if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
}
return nil
}
созданный клиентом
Когда у нас есть метод аутентификации, нужно сгенерировать ssh-client
sshClient, err := ssh.Dial("tcp", "host:port", sshConfig)
if err != nil {
return nil, fmt.Errorf("Failed to dial: %s", err)
}
После того, как соединение установлено, нам нужно создать сессию для выполнения команды.Сессия - это выполнение команды.Перед началом выполнения команды нам также необходимо создать сессию.псевдотерминал, для удобного ввода и вывода
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
return nil, fmt.Errorf("request for pseudo terminal failed: %s", err)
}
Затем мы можем приступить к выполнению кода, см. полный кодssh_client
Ссылаться на
how-to-create-an-ssh-tunnel-in-go