【SSH】SSHログイン時のチェック内容について
背景
前提
- OpenSSH バージョン: V_7_6_P1
- ログインユーザー名: Chiara
- ssh_config にて 厳格モードが有効である
- StrictModes yes ないし、コメントアウトされている
詳細
authorized_key の所有者・権限チェック
- 所有者(以下、いずれかを満たす)
- rootユーザー(ないし、root相当ユーザー)である
- 所有者が、ログインするユーザーになっている
- 権限
- グループ, その他ユーザーに書き込み権限がない
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/auth.c#L467
static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) { /// 一部省略 /// if (strict_modes && safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); auth_debug_add("Ignored %s: %s", file_type, line); return NULL; } /// 一部省略 /// }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1673
int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) < 0) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1608
int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { /// 一部省略 /// if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || (stp->st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for file %s", buf); return -1; } /// 一部省略 /// }
.ssh、ホームディレクトリの所有者・権限チェック
- 所有者(以下、いずれかを満たす)
- rootユーザー(ないし、root相当ユーザー)である
- 所有者が、ログインするユーザーになっている
- 権限
- グループ, その他ユーザーに書き込み権限がない
- チェック範囲
- /home/Chiara/.ssh
- /home/Chiara
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/auth.c#L467
static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) { /// 一部省略 /// if (strict_modes && safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); auth_debug_add("Ignored %s: %s", file_type, line); return NULL; } /// 一部省略 /// }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1673
int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) < 0) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1608
int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { /// 一部省略 /// /* for each component of the canonical path, walking upwards */ for (;;) { if ((cp = dirname(buf)) == NULL) { snprintf(err, errlen, "dirname() failed"); return -1; } strlcpy(buf, cp, sizeof(buf)); if (stat(buf, &st) < 0 || (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || (st.st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for directory %s", buf); return -1; } /* If are past the homedir then we can stop */ if (comparehome && strcmp(homedir, buf) == 0) break; /* * dirname should always complete with a "/" path, * but we can be paranoid and check for "." too */ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) break; } /// 一部省略 /// }
今後について
- authorized_key が rootユーザーでもいいような結果になったが、おそらく間違っていると思われます
- 今後調査をして、正しいものに修正します
ssh コマンドで host名を補完する
■前提
- /.ssh/known_hosts がハッシュ化されていない
■内容
~/.bashrc に以下のように記載することで、補完が可能になります。
$ cat ~/.bashrc function _complete_ssh() { if [ -f $HOME/.ssh/known_hosts ]; then local cur=${COMP_WORDS[COMP_CWORD]}; COMPREPLY=( $(compgen -W "`cat $HOME/.ssh/known_hosts | tr ',' ' ' | cut -d' ' -f1`2"-- $cur)) fi } complete -F _complete_ssh ssh
■使用例 ssh w を打ったところで、[tab]キーを押すと、wから始まるホストのみが候補として出て、該当が1件の場合、補完がされる。
■ ~/.ssh/known_hosts の表記例
以下のようにhash化されていない場合のみ使用可能
$ cat ~/.ssh/known_hosts web01,10.0.0.2 ssh-rsa AA...
■雑記
~/.ssh/known_hosts をハッシュ化した場合の運用の実例は、誰か記事にしているでしょうか?
アクセス可能なIPが分かりずらいのは、サーバーに入られたときに、そこを踏み台に 悪さされるのを難しくはできるでしょうが、今思いつく限りでは運用が面倒になりそうな気がして...
■参考になった記事
- known_hosts のハッシュ化について itiskj.hatenablog.com
AWS Certificate Manager で証明書を更新する(2018.11)
■背景
AWSで使用しているELB用の証明書を更新する機会があったため、 その際の操作手順をまとめました。 各種パラメータは、ダミーのものに置き換えています。
■前提
■更新手順
1. AWS コンソールから「AWS Certificate Manager 」を開きます。
開くと、以下のようなページが表示されます。
*.example.com を今回は更新していきます。
2. 「Reimport certificate」を押して、証明書を貼り付け、「Review and import」を押します。
- Certificate body: PEM 形式のサーバー証明書
- Certificate private key: PEM 形式の証明書のプライベートキー
- Certificate chain: PEM 形式の中間証明書 ※「空白行」があった場合、消した上で入力が必要なようです。
3. 取り込みした証明書が問題ないことを確認して、「Import」を押します。
4. 取り込みした証明書が反映されたことを確認します。
「Certificate Manager」トップから、*.example.com 欄の行をクリックして詳細を出します。
Expires in が延長されていることを確認します。
svn+ssh 接続しているリポジトリへの svn:externals 設定
■背景
svn+ssh で接続が可能なsvnリポジトリに、外部参照設定をする必要が出ました。
初めての設定で少し戸惑った部分があったので、設定からフェッチするところまでをまとめました。
■結論
以下の書式で設定ができます。 リポジトリのURL が、http:// と svn+ssh:// で特に違いはないようです。
svn propset svn:externals "[属性を付与するディレクトリ] [リポジトリのURL]" [ディレクトリの配置パス]
■使用例
以下の条件における、svn:externals設定の方法を記載します。
[chiara@web01]$ cd tmp [chiara@web01~/tmp]$ ls [chiara@web01~/tmp]$ svn propset svn:externals "test svn+ssh://chiara@svn/repos/hoge/trunk/test" . property 'svn:externals' set on '.' [chiara@web01~/tmp]$ svn proplist -v . Properties on '.': svn:externals test svn+ssh://chiara@svn/repos/hoge/trunk/test
※この時点では、まだプロパティの設定だけでtestディレクトリは作成されていません。 testディレクトリをsvn up しても変化はありません。
[chiara@web01 ~/tmp]$ ls [chiara@web01 ~/tmp]$ svn up test At revision 10. [chiara@web01 ~/tmp]$ ls
プロパティの設定がされた tmp ディレクトリを svn up することで、初めて testディレクトリがフェッチされます。
[chiara@web01 ~/tmp]$ svn up . Fetching external item into 'test' A hoge.png Updated external to revision 10. Updated to revision 10.
【トラブル対応】td-agent(fluentd) 再起動時の "Address already in use" エラー
■背景
- 複数台のWebサーバーのログを、td-agent によって、1台のログ集約サーバーに送っている
- Webサーバー の td-agentをstepし、ログ集約サーバーの td-agent をrestart した
- Webサーバーのtd-agentをstart すると ログ集約サーバーのポートにアクセスできないエラー出て、ログが送れなくなった
- ログ集約サーバーのtd-agent のログには "Address already in use" のエラーが出た
■環境
- td-agent v1.1.12
- fluentd v0.10.33
■原因
- ログ集約サーバーの td-agent を restart した際に、プロセスが残っていて、ポートが占有されたままになっていた
■対応
- Webサーバーの td-agent を stop
- ログ集約サーバーの td-agent を stop した上で、同サーバーの td-agent のプロセスを殺した
- ログ集約サーバーのtd-agent を start
- Webサーバーのtd-agent を start
■今回学んだこと
- td-agent restart では、プロセスが残ってしまう場合がある
■トラブル発覚までの操作
1. webサーバーの td-agent を停止
[chiara@web01 ~]$ sudo /etc/init.d/td-agent stop
2. ログ集約サーバーの td-agent を再起動
[chiara@log ~]$ sudo /etc/init.d/td-agent stop
3. webサーバーの td-agent を開始
[chiara@web01 ~]$ sudo /etc/init.d/td-agent stop
4. Webサーバーのtd-agentのログを確認
ログ集約サーバーに接続できないエラーが発生した
[chiara@web01 ~]$ sudo cat /var/log/td-agent/td-agent.log 2018-11-01 10:55:00 +0900 [info]: detached forwarding server 'log' host="log" port=24224 hard_timeout=true
5. ログ集約サーバーのtd-agent のログを確認
ポート: 24224 が既に使われているエラーが発生していた
[chiara@log ~]$ sudo cat /var/log/td-agent/td-agent.log 2018-11-01 11:00:00 +0900 [info]: listening fluent socket on 0.0.0.0:24224 2018-11-01 11:00:00 +0900 [error]: unexpected error error="Address already in use - bind(2)" 2018-11-01 11:00:00 +0900 [error]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/cool.io-1.1.1/lib/cool.io/server.rb:57:in `initialize' 2018-11-01 11:00:00 +0900 [error]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/cool.io-1.1.1/lib/cool.io/server.rb:57:in `new' 2018-11-01 11:00:00 +0900 [error]: /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/cool.io-1.1.1/lib/cool.io/server.rb:57:in `initialize'
■調査内容
ログ集約サーバーのtd-agentのプロセスを確認
確認すると、4つのプロセスが確認できた td-agent は、データ通信(TCP), UDP(死活監視) で2プロセス使うので、それ以外の2プロセスが余計に見える。
[chiara@log ~]$ ps aux | grep td-agent | grep -v grep root 3580 0.0 0.5 841112 89744 ? Sl Oct29 0:37 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid root 14311 78.0 0.1 723748 31088 ? Rl 11:15 0:00 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid root 24111 0.0 0.5 841112 87232 ? S Oct29 0:00 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid root 29982 0.0 0.0 168292 14516 ? Sl 11:15 0:00 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid
td-agent を停止後に再度プロセスを確認
stop しても消えないプロセスが残っていた
[chiara@log ~]$ sudo /etc/init.d/td-agent stop Shutting down td-agent: [ OK ] [chiara@log ~]$ ps aux | grep td-agent | grep -v grep root 3580 0.0 0.5 841112 89744 ? Sl Oct29 0:37 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid root 24111 0.0 0.5 841112 87232 ? S Oct29 0:00 /usr/lib64/fluent/ruby/bin/ruby /usr/sbin/td-agent --group root --log /var/log/td-agent/td-agent.log --daemon /var/run/td-agent/td-agent.pid
■対応内容
不要なプロセスをkillコマンドで殺した
[chiara@log ~]$ sudo kill -9 24111 3580