V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
helloworld12
V2EX  ›  问与答

Linux ssh 自动输入

  •  
  •   helloworld12 · 2018-08-31 10:24:24 +08:00 · 2704 次点击
    这是一个创建于 2281 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一段脚本 里面的一个函数需要用到 ssh 譬如

    f() {
    	    ssh -tt $ser << EOF
    		echo "do something"
        EOF
        }
    

    我要怎样把密码传给 ssh ( ssh 的秘钥是需要密码的)

    用 expect 的方案好像不行,我有许多命令需要再 bash 环境下里面进行,且密码不能直接写在脚本里,只能运行的时候输入进来

    19 条回复    2018-08-31 21:23:25 +08:00
    xinhangliu
        1
    xinhangliu  
       2018-08-31 10:30:52 +08:00 via Android
    SSH 免密登录?
    xinhangliu
        2
    xinhangliu  
       2018-08-31 10:33:26 +08:00 via Android
    或者 `read -s -p "Password: "`?
    jasonyang9
        3
    jasonyang9  
       2018-08-31 10:35:13 +08:00
    设定下 rsa 密钥登录,并用`-i`指定私钥
    jasonyang9
        4
    jasonyang9  
       2018-08-31 10:35:38 +08:00
    看错了,请忽略
    helloworld12
        5
    helloworld12  
    OP
       2018-08-31 10:53:53 +08:00
    @xinhangliu 要密码,怕秘钥外流

    或者 `read -s -p "Password: "`? xxx
    现在的问题,是要怎么把 xxx 传给 ssh 命令
    Goooogle
        6
    Goooogle  
       2018-08-31 11:00:52 +08:00
    Expect 也是可以的
    我从自己的配置里复制出来一部分 应该能满足你需求

    ```

    # 提醒用户输入密码
    send "'$PROMPT_FOR_PASSWORD'";

    # 将用户输入的密码保存到临时变量中
    stty -echo;
    expect_user -timeout 3600 -re "(.*)\n";
    set PASSWORD $expect_out(1,string);
    stty echo;

    # 登录
    spawn ssh -i '$SSH_PEM_FILE' \
    '$SSH_USER_NAME'@'$SSH_JUMP_SERVER';
    expect {
    # 自动输入密码
    -re "Enter passphrase for key" {
    if {$PASSWORD == ""} {
    exit;
    }
    send "$PASSWORD\n";
    exp_continue;
    }
    }

    ```
    kikyous
        7
    kikyous  
       2018-08-31 11:01:48 +08:00
    sshagent
    Goooogle
        8
    Goooogle  
       2018-08-31 11:03:43 +08:00
    这段配置的原始用途是配合 iterm2 的 Trigger 和 Password Manager 免输入密码登录 JumpServer 并自动选择对应的机器并 attach 到 tmux
    ysc3839
        9
    ysc3839  
       2018-08-31 11:06:03 +08:00
    sshpass
    ysc3839
        10
    ysc3839  
       2018-08-31 11:07:40 +08:00
    @ysc3839 我好像理解错了?是密钥需要密码而不是远程服务器需要密码?那 sshpass 不适用。
    kinnveeee
        11
    kinnveeee  
       2018-08-31 11:29:48 +08:00
    sshpass -P "Enter passphrase for key" -p 密钥密码 ssh -i 密钥 用户名 @主机名 /ip -P 端口
    helloworld12
        12
    helloworld12  
    OP
       2018-08-31 15:29:01 +08:00
    @Goooogle 谢谢 嗯, 脚本里面还有其他内容,需要 bash 环境, 所以 expect 不合适
    @kinnveeee
    @ysc3839 sshpass 不适用 秘钥密码
    msg7086
        13
    msg7086  
       2018-08-31 15:43:33 +08:00
    你换个思路。如果你私钥都能泄露了,那你写在脚本里的密码会不泄露吗。

    所以为什么不直接用无密码密钥呢。只要不带出这台机器不就没事了么。
    Goooogle
        14
    Goooogle  
       2018-08-31 15:47:51 +08:00   ❤️ 1
    @helloworld12
    "脚本里面还有其他内容,需要 bash 环境" 这句话什么意思,不是很理解。
    连上后还需要在服务器上手动 /自动执行脚本?


    如果需要自动执行 在 expect 登陆后 send 命令就好
    如果需要手动操作 可以 expect 登陆后 interact
    zhangjn
        15
    zhangjn  
       2018-08-31 16:03:05 +08:00   ❤️ 1
    putty 的 pageant 有管理密钥的功能,只要一开始输入一次 key 的密码就行。
    openssh 有个对应的 ssh-agent

    直接用密码的时候为了不用输入密码,我魔改了 openssh,用环境变量当密码, 比改称用参数稍微安全一丁点
    PS: 用 LFS ( linux from scratch )就是这点方便,就是全构建一次要几个小时

    魔改 patch 如下, 你可以照猫画虎把 key 密码的读取也改成这样的
    ```
    diff -urz openssh-7.7p1.orig/readpass.c openssh-7.7p1/readpass.c
    --- openssh-7.7p1.orig/readpass.c
    +++ openssh-7.7p1/readpass.c
    @@ -47,9 +47,17 @@
    #include "ssh.h"
    #include "uidswap.h"

    +static char *_env_pass(void)
    +{
    + return getenv("_SSH_PASS"); // 运行的时候 _SSH_PASS=<password> ssh username@host 就行了
    +}
    +
    static char *
    ssh_askpass(char *askpass, const char *msg)
    {
    + if(_env_pass())
    + return xstrdup(_env_pass());
    +
    pid_t pid, ret;
    size_t len;
    char *pass;
    @@ -118,6 +126,13 @@ ssh_askpass(char *askpass, const char *m
    char *
    read_passphrase(const char *prompt, int flags)
    {
    + if (_env_pass()) {
    + if (strstr(prompt, "Please type 'yes'")) {
    + return xstrdup("yes");
    + }
    + return xstrdup(_env_pass());
    + }
    +
    char *askpass = NULL, *ret, buf[1024];
    int rppflags, use_askpass = 0, ttyfd;

    @@ -169,6 +184,9 @@ read_passphrase(const char *prompt, int
    int
    ask_permission(const char *fmt, ...)
    {
    + if(_env_pass())
    + return 1;
    +
    va_list args;
    char *p, prompt[1024];
    int allowed = 0;

    ```
    zhangjn
        16
    zhangjn  
       2018-08-31 16:03:51 +08:00
    回复不支持 makrdown 啊, 格式乱了
    helloworld12
        17
    helloworld12  
    OP
       2018-08-31 16:21:44 +08:00
    @zhangjn 谢谢, 搜了下 ssh-agent 学到了新知识

    不过不适用, 因为希望每次运行脚本的时候,都去输入密码(即使对本机也不信任。。。)
    zhangjn
        18
    zhangjn  
       2018-08-31 16:34:37 +08:00   ❤️ 1
    @helloworld12 #17 用的 VPS 么,pageant 和 ssh-agent 还能支持链式转发, 即这两个软件运行在本地,被 ssh 登录的机器也可以使用本地的 keys,但是这样依然解决不了对 vps 的信任问题,顶多在本地的 ssh-agent 里面加上日志然后审计。

    合理的解决方法是密码不能在不信任的机器上出现,如果只是为了使用不信任机器的网络可以用 vpn 或者其他的代理软件
    helloworld12
        19
    helloworld12  
    OP
       2018-08-31 21:23:25 +08:00
    @zhangjn 对本机不信任是因为, 老板说, 有人家里在运行的电脑被黑了,然后顺着电脑把服务器也给黑了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6030 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:44 · PVG 10:44 · LAX 18:44 · JFK 21:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.