Telegram の非公式cli client の telegram-cli を試す

Arm でも動くかな?と試してみました.

必要パッケージの導入
$ sudo apt install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make libssl1.0-dev
sourceをcloneする
$ git clone --recursive https://github.com/vysheng/tg.git && cd tg
configure & make
$ ./configure
$ make
build error1
tgl/crypto/rsa_pem_openssl.c: In function ‘TGLC_rsa_new’:
tgl/crypto/rsa_pem_openssl.c:41:6: error: dereferencing pointer to incomplete type ‘RSA {aka struct rsa_st}’
   ret->e = unwrap_bn (TGLC_bn_new ());
      ^~
tgl/crypto/rsa_pem_openssl.c: In function ‘TGLC_rsa_n’:
tgl/crypto/rsa_pem_openssl.c:52:1: error: control reaches end of non-void function [-Werror=return-type]
 RSA_GETTER(n);
 ^~~~~~~~~~
tgl/crypto/rsa_pem_openssl.c: In function ‘TGLC_rsa_e’:
tgl/crypto/rsa_pem_openssl.c:53:1: error: control reaches end of non-void function [-Werror=return-type]
 RSA_GETTER(e);
 ^~~~~~~~~~
cc1: all warnings being treated as errors
Makefile.tgl:20: recipe for target 'objs/crypto/rsa_pem_openssl.o' failed
make: *** [objs/crypto/rsa_pem_openssl.o] Error 1

libssl-dev(1.1.1)では動作しないのでlibssl1.0-devに入れ替える. sudo apt install libssl1.0-dev

build error2
gcc -I. -I. -I./tgl -w  -I/usr/local/include -I/usr/include -I/usr/include -I/usr/include/lua5.2  -DHAVE_CONFIG_H -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC -iquote ./tgl/tl-parser -c -MP -MD -MF dep/tl-parser.d -MQ objs/tl-parser.o -o objs/tl-parser.o tgl/tl-parser/tl-parser.c
tgl/tl-parser/tl-parser.c:37:10: fatal error: zlib.h: そのようなファイルやディレクトリはありません
 #include <zlib.h>
          ^~~~~~~~
compilation terminated.
make: *** [Makefile.tl-parser:4: objs/tl-parser.o] エラー 1

zlib1g-dev を導入する. sudo apt install zlib1g-dev

Raspbian stretchでの実行時エラー(32bit環境での不具合?)
$ bin/telegram-cli
Telegram-cli version 1.4.1, Copyright (C) 2013-2015 Vitaly Valtman
Telegram-cli comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show_license' for details.
Telegram-cli uses libtgl version 2.1.0
Telegram-cli includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
I: config dir=[/home/pi/.telegram-cli]
> telegram-cli: tgl/mtproto-utils.c:101: BN2ull: Assertion `0' failed.
SIGNAL received

以下の修正を行い, make clean して build しなおす.

$ diff -ud tgl/mtproto-utils.c.org tgl/mtproto-utils.c
--- tgl/mtproto-utils.c.org     2018-09-19 21:01:44.878560077 +0900
+++ tgl/mtproto-utils.c 2018-09-19 20:59:55.778295550 +0900
@@ -98,13 +98,13 @@
   if (sizeof (unsigned long) == 8) {
	 return TGLC_bn_get_word (b);
   } else if (sizeof (unsigned long long) == 8) {
-    assert (0); // As long as nobody ever uses this code, assume it is broken.
+    assert (0);  As long as nobody ever uses this code, assume it is broken.
	 unsigned long long tmp;
	 /* Here be dragons, but it should be okay due to be64toh */
	 TGLC_bn_bn2bin (b, (unsigned char *) &tmp);
	 return be64toh (tmp);
   } else {
-    assert (0);
+//    assert (0);
   }
 }
$ make clean
$ ./configure
$ make
初回実行時はSMS認証が必要
$ bin/telegram-cli
Telegram-cli version 1.4.1, Copyright (C) 2013-2015 Vitaly Valtman
Telegram-cli comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show_license' for details.
Telegram-cli uses libtgl version 2.1.0
Telegram-cli includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
I: config dir=[/home/mk/.telegram-cli]
[/home/mk/.telegram-cli] created
[/home/mk/.telegram-cli/downloads] created
phone number: +81-9000000000
code ('CALL' for phone code): 16802
User matoken updated flags
User matoken online (was online [2018/09/18 23:55:32])
User matoken offline (was online [2018/09/18 23:50:35])
認証を行うとメッセージが飛んでくる
matoken,

We detected a login into your account from a new device on 19/09/2018 at 12:28:55 UTC.

Device: Unix Console
Location: Shizuoka, Japan (IP = 180.131.110.140)

If this wasn't you, you can go to Settings - Privacy and Security - Sessions and terminate that session.

If you think that somebody logged in to your account against your will, you can enable two-step verification in Privacy and Security settings.

Sincerely,
The Telegram Team
メッセージを送信してみる
> msg @matoken hello
telegram-cli の help
$ bin/telegram-cli --help
telegram-cli Usage
  --phone/-u                           specify username (would not be asked during authorization)
  --rsa-key/-k                         specify location of public key (possible multiple entries)
  --verbosity/-v                       increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels)
  --enable-msg-id/-N                   message num mode
  --config/-c                          config file name
  --profile/-p                         use specified profile
  --log-level/-l                       log level
  --sync-from-start/-f                 during authorization fetch all messages since registration
  --disable-auto-accept/-E             disable auto accept of encrypted chats
  --lua-script/-s                      lua script file
  --wait-dialog-list/-W                send dialog_list query and wait for answer before reading input
  --disable-colors/-C                  disable color output
  --disable-readline/-R                disable readline
  --alert/-A                           enable bell notifications
  --daemonize/-d                       daemon mode
  --logname/-L <log-name>              log file name
  --username/-U <user-name>            change uid after start
  --groupname/-G <group-name>          change gid after start
  --disable-output/-D                  disable output
  --tcp-port/-P <port>                 port to listen for input commands
  --udp-socket/-S <socket-name>        unix socket to create
  --exec/-e <commands>                 make commands end exit
  --disable-names/-I                   use user and chat IDs in updates instead of names
  --enable-ipv6/-6                     use ipv6 (may be unstable)
  --help/-h                            prints this help
  --accept-any-tcp                     accepts tcp connections from any src (only loopback by default)
  --disable-link-preview               disables server-side previews to links
  --bot/-b                             bot mode
  --json                               prints answers and values in json format
  --permanent-msg-ids                  use permanent msg ids
  --permanent-peer-ids                 use permanent peer ids
telegram-cli 起動時のhelp
$ bin/telegram-cli -e help
Telegram-cli version 1.4.1, Copyright (C) 2013-2015 Vitaly Valtman
Telegram-cli comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show_license' for details.
Telegram-cli uses libtgl version 2.1.0
Telegram-cli includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
I: config dir=[/home/pi/.telegram-cli]
[33;1maccept_secret_chat <secret chat>  Accepts secret chat. Only useful with -E option
add_contact <phone> <first name> <last name>    Tries to add user to contact list
block_user <user>       Blocks user
broadcast <user>+ <text>        Sends text to several users at once
channel_get_admins <channel> [limit=100] [offset=0]     Gets channel admins
channel_get_members <channel> [limit=100] [offset=0]    Gets channel members
channel_info <channel>  Prints info about channel (id, members, admin, etc.)
channel_invite <channel> <user> Invites user to channel
channel_join <channel>  Joins to channel
channel_kick <channel> <user>   Kicks user from channel
channel_leave <channel> Leaves from channel
channel_list [limit=100] [offset=0]     List of last channels
channel_set_about <channel> <about>     Sets channel about info.
channel_set_admin <channel> <admin> <type>      Sets channel admin. 0 - not admin, 1 - moderator, 2 - editor
channel_set_username <channel> <username>       Sets channel username info.
channel_set_photo <channel> <filename>  Sets channel photo. Photo will be cropped to square
chat_add_user <chat> <user> [msgs-to-forward]   Adds user to chat. Sends him last msgs-to-forward message from this chat. Default 100
chat_del_user <chat> <user>     Deletes user from chat
chat_info <chat>        Prints info about chat (id, members, admin, etc.)
chat_set_photo <chat> <filename>        Sets chat photo. Photo will be cropped to square
chat_upgrade <chat>     Upgrades chat to megagroup
chat_with_peer <peer>   Interface option. All input will be treated as messages to this peer. Type /quit to end this mode
clear   Clears all data and exits. For debug.
contact_list    Prints contact list
contact_search username Searches user by username
create_channel <name> <about> <user>+   Creates channel with users
create_group_chat <name> <user>+        Creates group chat with users
create_secret_chat <user>       Starts creation of secret chat
del_contact <user>      Deletes contact from contact list
delete_msg <msg-id>     Deletes message
dialog_list [limit=100] [offset=0]      List of last conversations
export_card     Prints card that can be imported by another user with import_card method
export_channel_link     Prints channel link that can be used to join to channel
export_chat_link        Prints chat link that can be used to join to chat
fwd <peer> <msg-id>+    Forwards message to peer. Forward to secret chats is forbidden
fwd_media <peer> <msg-id>       Forwards message media to peer. Forward to secret chats is forbidden. Result slightly differs from fwd
get_terms_of_service    Prints telegram's terms of service
get_message <msg-id>    Get message by id
get_self        Get our user info
help [command]  Prints this help
history <peer> [limit] [offset] Prints messages with this peer (most recent message lower). Also marks messages as read
import_card <card>      Gets user by card and prints it name. You can then send messages to him as usual
import_chat_link <hash> Joins to chat by link
import_channel_link <hash>      Joins to channel by link
load_audio <msg-id>     Downloads file to downloads dirs. Prints file name after download end
load_channel_photo <channel>    Downloads file to downloads dirs. Prints file name after download end
load_chat_photo <chat>  Downloads file to downloads dirs. Prints file name after download end
load_document <msg-id>  Downloads file to downloads dirs. Prints file name after download end
load_document_thumb <msg-id>    Downloads file to downloads dirs. Prints file name after download end
load_file <msg-id>      Downloads file to downloads dirs. Prints file name after download end
load_file_thumb <msg-id>        Downloads file to downloads dirs. Prints file name after download end
load_photo <msg-id>     Downloads file to downloads dirs. Prints file name after download end
load_user_photo <user>  Downloads file to downloads dirs. Prints file name after download end
load_video <msg-id>     Downloads file to downloads dirs. Prints file name after download end
load_video_thumb <msg-id>       Downloads file to downloads dirs. Prints file name after download end
main_session    Sends updates to this connection (or terminal). Useful only with listening socket
mark_read <peer>        Marks messages with peer as read
msg <peer> <text>       Sends text message to peer
msg <peer> <kbd> <text> Sends text message to peer with custom kbd
post <peer> <text>      Sends text message to peer as admin
post_audio <peer> <file>        Posts audio to peer
post_document <peer> <file>     Posts document to peer
post_file <peer> <file> Sends document to peer
post_location <peer> <latitude> <longitude>     Sends geo location
post_photo <peer> <file>       Sends photo to peer
post_text <peer> <file> Sends contents of text file as plain text message
post_video <peer> <file>       Sends video to peer
quit    Quits immediately
rename_channel <channel> <new name>     Renames channel
rename_chat <chat> <new name>   Renames chat
rename_contact <user> <first name> <last name>  Renames contact
reply <msg-id> <text>   Sends text reply to message
reply_audio <msg-id> <file>     Sends audio to peer
reply_contact <msg-id> <phone> <first-name> <last-name> Sends contact (not necessary telegram user)
reply_document <msg-id> <file>  Sends document to peer
reply_file <msg-id> <file>      Sends document to peer
reply_location <msg-id> <latitude> <longitude>  Sends geo location
reply_photo <msg-id> <file>    Sends photo to peer
reply_video <msg-id> <file>     Sends video to peer
resolve_username username       Searches user by username
safe_quit       Waits for all queries to end, then quits
search [peer] [limit] [from] [to] [offset] pattern      Search for pattern in messages from date from to date to (unixtime) in messages with peer (if peer not
present, in all messages)
send_audio <peer> <file>        Sends audio to peer
send_contact <peer> <phone> <first-name> <last-name>    Sends contact (not necessary telegram user)
send_document <peer> <file>     Sends document to peer
send_file <peer> <file> Sends document to peer
send_location <peer> <latitude> <longitude>     Sends geo location
send_photo <peer> <file>       Sends photo to peer
send_text <peer> <file> Sends contents of text file as plain text message
send_typing <peer> [status]     Sends typing notification. You can supply a custom status (range 0-10): none, typing, cancel, record video, upload video, recor
d audio, upload audio, upload photo, upload document, geo, choose contact.
send_typing_abort <peer>        Sends typing notification abort
send_video <peer> <file>       Sends video to peer
set <param> <value>     Sets value of param. Currently available: log_level, debug_verbosity, alarm, msg_num
set_password <hint>     Sets password
set_profile_name <first-name> <last-name>       Sets profile name.
set_profile_photo <filename>    Sets profile photo. Photo will be cropped to square
set_ttl <secret chat>   Sets secret chat ttl. Client itself ignores ttl
set_username <name>     Sets username.
set_phone_number <phone>        Changes the phone number of this account
show_license    Prints contents of GPL license
start_bot <bot> <chat> <data>   Adds bot to chat
stats   For debug purpose
status_online   Sets status as online
status_offline  Sets status as offline
unblock_user <user>     Unblocks user
user_info <user>        Prints info about user (id, last online, phone)
version Prints client and library version
view_audio <msg-id>     Downloads file to downloads dirs. Then tries to open it with system default action
view_channel_photo <channel>    Downloads file to downloads dirs. Then tries to open it with system default action
view_chat_photo <chat>  Downloads file to downloads dirs. Then tries to open it with system default action
view_document <msg-id>  Downloads file to downloads dirs. Then tries to open it with system default action
view_document_thumb <msg-id>    Downloads file to downloads dirs. Then tries to open it with system default action
view_file <msg-id>      Downloads file to downloads dirs. Then tries to open it with system default action
view_file_thumb <msg-id>        Downloads file to downloads dirs. Then tries to open it with system default action
view_photo <msg-id>     Downloads file to downloads dirs. Then tries to open it with system default action
view_user_photo <user>  Downloads file to downloads dirs. Then tries to open it with system default action
view_video <msg-id>     Downloads file to downloads dirs. Then tries to open it with system default action
view_video_thumb <msg-id>       Downloads file to downloads dirs. Then tries to open it with system default action
view <msg-id>   Tries to view message contents
visualize_key <secret chat>     Prints visualization of encryption key (first 16 bytes sha1 of it in fact)
[0mAll done. Exit
halt

大抵のことは出来る感じです.

試した環境1
$ git log --decorate|head -7
commit 6547c0b21b977b327b3c5e8142963f4bc246187a (HEAD -> master, origin/master, origin/HEAD)
Merge: 443793d 160231b
Author: V V <vvaltman@aurum>
Date:   Wed Mar 23 14:42:53 2016 +0300

    Merge github.com:vysheng/tg

$ dpkg-query -W libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make libssl1.0-dev
libconfig-dev:armhf     1.5-0.3
libevent-dev    2.0.21-stable-3
libjansson-dev:armhf    2.9-1
liblua5.2-dev:armhf     5.2.4-1.1
libpython-dev:armhf     2.7.13-2
libreadline-dev:armhf   7.0-3
libssl-dev
libssl1.0-dev:armhf     1.0.2l-2+deb9u3
lua5.2  5.2.4-1.1
make    4.1-9.1
$ lsb_release -d
Description:    Raspbian GNU/Linux 9.4 (stretch)
$ uname -m
armv7l
$ cat /proc/device-tree/model ;echo
Raspberry Pi 2 Model B Rev 1.1
試した環境2
$ git log --decorate|head -7
commit 6547c0b21b977b327b3c5e8142963f4bc246187a (HEAD -> master, origin/master, origin/HEAD)
Merge: 443793d 160231b
Author: V V <vvaltman@aurum>
Date:   Wed Mar 23 14:42:53 2016 +0300

    Merge github.com:vysheng/tg

$ dpkg-query -W libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make libssl1.0-dev
libconfig-dev:amd64     1.5-0.4
libevent-dev    2.1.8-stable-4build1
libjansson-dev:amd64    2.11-1
liblua5.2-dev:amd64     5.2.4-1.1build1
libpython-dev:amd64     2.7.15~rc1-1
libreadline-dev:amd64   7.0-3
libssl-dev
libssl1.0-dev:amd64     1.0.2n-1ubuntu5.1
lua5.2  5.2.4-1.1build1
make    4.1-9.1ubuntu1
$ lsb_release -d
Description:    Ubuntu 18.04.1 LTS
(mk)-(jobs:0)-(~/src/tg)
$ uname -m
x86_64

デーモンの起動しないSMTPクライアントの msmtp を試す(sSMTP乗り換え)

sSMTP から msmtp へ

現在メールを受け取らずメールを送信するだけのホストではsSMTPをよく使っています.MTAはeximやPostfix等でも良いのですが,デーモンが起動しないのでその分セキュアで設定も楽です.
しかし,sSMTPは最近メンテされていません,Debian などのディストリビューションではまだメンテナンスされていますが新機能が入ったりはしないでしょう.

ssmtp is unmaintained. Consider using something like msmtp instead.
バージョンも据え置きでUpstreamも無さそう
$ w3m -dump https://packages.qa.debian.org/s/ssmtp.html|grep versions -A11
versions ... ...pool

o-o-stable
    save 2.64-7
oldstable
    save 2.64-8
stable
    save 2.64-8
unstable
    save 2.64-8
Ubuntu
    2.64-8ubuntu2
$ apt show ssmtp 2>/dev/null |grep Homepage
Homepage: http://packages.qa.debian.org/s/ssmtp.html

そこで,alternativeto.net で挙げられている msmtp を試してみました.

以下では色々試していますが,システムメールを送るだけなら msmtp, msmtp-mta pkg を導入,/etc/msmtprc の設定だけでokです.

msmtp の導入

Debian sid/Ubuntu 18.04 LTS などではパッケージがあったのでこれを導入しました.

$ sudo apt install msmtp

mstpの設定

設定例が /usr/share/doc/msmtp/examples/ 以下にあるので
システム設定の場合は msmtprc-system.example`/etc/msmtprc にcpして設定.
ユーザ設定の場合は msmtprc-user.example~/.msmtprc にcpして設定する.

システムでの設定例

以下の例では root が読み書きできて,一般ユーザのmatokenアカウントは読み込みが可能な設定ファイル /etc/msmtprc を作成している.
defaults セクションに共通設定を書き,account セクションにメールサーバ固有の設定を書く.account セクションは複数書けて,account default に規定account を指定する.以下の例ではgmail が規定値となる.

/etc/msmtprc の作成
$ sudo install /dev/null /etc/msmtprc -o root -g root -m 600
$ sudo setfacl -m u:matoken:r /etc/msmtprc
$ getfacl /etc/msmtprc
getfacl: Removing leading '/' from absolute path names
# file: etc/msmtprc
# owner: root
# group: root
user::rw-
user:matoken:r--
group::---
mask::r--
other::---

$ sudo vi /etc/msmtprc
$ sudo grep -v ^# /etc/msmtprc

defaults
syslog on
aliases /etc/aliases

tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
auth on
syslog LOG_MAIL

account gmail
host smtp.gmail.com
port 587
from example@gmail.com
user example
password porseypacdoadwif

account default : gmail

※gmailの多要素認証を利用している場合は以下からアプリパスワードを生成する.(使い回しができちゃうけれど流出したときの影響を考えて設定毎に発行する)

ユーザでの設定

ユーザの設定ファイルは`~/.msmtprc` 若しくは $XDG_CONFIG_HOME/msmtp/config でシステムと違い,alias file と log を適当なファイルにした.
アカウントも増やしてみた.
gmailのアプリパスワードも新たに発行した.

~/.msmtprc の作成
$ install /dev/null ~/.msmtprc -o matoken -g matoken -m 600
$ vi ~/.msmtprc
$ grep -v ^# ~/.msmtprc

defaults
logfile ~/.msmtp.log
aliases ~/.msmtp.aliases

tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
auth on
syslog LOG_MAIL

account gmail
host smtp.gmail.com
port 587
from example@gmail.com
user example
password igeinleedafchygy

account yandex
tls_starttls off
host smtp.yandex.com
port 465
from example@yandex.com
user example
password throjfeekdewxeib

account nifty
tls_starttls off
host smtp.nifty.com
port 465
from example@nifty.com
user aaa99999
password 9Z#9999X

account default : gmail

送信テスト

msmtp コマンドで送信テストが出来る.
-a オプションでアカウントが指定できる.
-C オプションで設定ファイルが指定できる.(システムとユーザの設定を両方テストする)

$ echo "hello system msmtp" | msmtp -C /etc/msmtprc matohara@gmail.com
$ echo "hello user msmtp" | msmtp -C ~/.msmtprc -a gmail matohara@gmail.com

大抵のMTAでは . でmail body 終了となるが,msmtpでは`.`は普通にbody に含まれる.Ctrl + d で終了.

$ msmtp -a gmail matohara@gmail.com
Subject: hello

msmtp test
.
dot では終了にならない
Ctrl+d で終了
^d

aliases file

msmtp設定ファイルの alias で設定できる.

$ grep alias ~/.msmtprc
aliases ~/.msmtp.alias
$ sudo grep alias /etc/msmtprc
aliases /etc/aliases

このalias fileは通常のaliases ファイルと同じ形式の plain text で newaliases コマンドでの変換は不要.

メールアドレスは複数指定できる.default という名前は規定アドレスとなる.

root: hoge@example.com, fuga@example.com
default: piyo@example.com

以前のaliases ファイルを流用して以下のようにしてみたところ,

# /etc/aliases
mailer-daemon: postmaster
postmaster: root
nobody: root
hostmaster: root
usenet: root
news: root
webmaster: root
www: root
ftp: root
abuse: root
noc: root
security: root
root: matohara@gmail.com
default: matohara@gmail.com

以下のようにエラーとなった.alias先はユーザ名ではエラーとなるよう.

$ echo hello | sudo msmtp -C /etc/msmtprc root
msmtp: /etc/aliases: line 2: invalid address 'postmaster'

以下のようにそれぞれにメールアドレスを指定すると期待した動作となった.

$ sudo sed -i -e 's/ root$\| postmaster$/matohara@gmail.com/' /etc/aliases
$ cat /etc/aliases
# /etc/aliases
mailer-daemon:matohara@gmail.com
postmaster:matohara@gmail.com
nobody:matohara@gmail.com
hostmaster:matohara@gmail.com
usenet:matohara@gmail.com
news:matohara@gmail.com
webmaster:matohara@gmail.com
www:matohara@gmail.com
ftp:matohara@gmail.com
abuse:matohara@gmail.com
noc:matohara@gmail.com
security:matohara@gmail.com
root: matohara@gmail.com
default: matohara@gmail.com

パスワードをGnuPG暗号化ファイルに格納して利用する

パスワードをgpgで暗号化したファイルに格納することが可能.この場合アカウントごとにファイルが必要なのが少し面倒.
password porseypacdoadwif の場合 porseypacdoadwif 部分だけを暗号化してファイルに格納する.(はじめpassword も含めてしまい失敗した)

$ grep ^password\  ~/.msmtprc | head -1 | awk {'print $2'} | gpg2 --default-recipient-self -e - > ~/.msmtp-password-gmail.gpg
$ grep ^password\  ~/.msmtprc | head -2 | tail -1 | awk {'print $2'} | gpg2 --default-recipient-self -e - > ~/.msmtp-password-yandex.gpg
$ grep ^password\  ~/.msmtprc | tail -1 | awk {'print $2'} | gpg2 --default-recipient-self -e - > ~/.msmtp-password-nifty.gpg

msmtprc の password を削除して,代わりに passwordeval gpg2 --no-tty -q -d 暗号ファイル と設定を変更する.

$ grep ^passworde ~/.msmtprc
passwordeval gpg2 --no-tty -q -d ~/.msmtp-password-gmail.gpg
passwordeval gpg2 --no-tty -q -d ~/.msmtp-password-yandex.gpg
passwordeval gpg2 --no-tty -q -d ~/.msmtp-password-nifty.gpg

後はこれまでのようにmsmtpを呼ぶとgpg-agentが起動する.

※システム側はシステムメールが送れなくなるのでこの設定をしないほうがいいと思う.

パスワードをopenssl暗号化ファイルに格納

システムメールでgpg agentを利用するのは多分無理なのでopensslで暗号化してみる.パスワードはNICのmac addressにしてある.気休めレベルだけど試しに設定.
マシンが乗っ取られた場合はどうしようもないけれど /etc/msmtprc, /etc/msmtp-password ファイル流出時の時間稼ぎくらいにはなる?
NIC が使っていないものも含め増減したり変更になった場合は復元できなくなるので注意.

mac address をパスワードとしてopensslで暗号化
$ umask 0077; grep ^password\  /etc/msmtprc | head -1 | awk {'print $2'} | sudo openssl enc -e -md sha256 -aes-256-cbc -a -A -salt -pbkdf2 -in /dev/stdin -out /etc/msmtp-password -pass pass:`hwinfo --network | grep 'Permanent HW Address' | sed 's/^.*: //' | sort -n | tr -d '\n'`
復元テスト
$ sudo openssl enc -d -md sha256 -aes-256-cbc -a -A -salt -pbkdf2 -in /etc/msmtp-password -pass pass:`hwinfo --network | grep 'Permanent HW Address' | sed 's/^.*: //' | sort -n | tr -d '\n'`
igeinleedafchygy
/etc/msmtprc の password を削除して passwordeval に書き換え
$ grep passworde /etc/msmtprc
passwordeval openssl enc -d -md sha256 -aes-256-cbc -a -A -salt -pbkdf2 -in /etc/msmtp-password -pass pass:`hwinfo --network | grep 'Permanent HW Address' | sed 's/^.*: //' | sort -n | tr -d '\n'`

※ifconfigやiproute2を使わずhwinfoを使ってPermanent HW Addressを使っているのはmac address偽装対策

MTA パッケージの導入

msmtp コマンドでメールが送信できるようになったら,msmtp-mta pkg を導入する.これでsendmailコマンドにシンボリックリンクが張られて同様に利用できるようになる.システムメールも飛ぶようになる.

$ sudo apt install msmtp-mta
$ ls -l /usr/sbin/sendmail
lrwxrwxrwx 1 root root 12 11月 29  2016 /usr/sbin/sendmail -> ../bin/msmtp

オフライン時にmsmtpを利用する

msmtpはオフライン時に実行するとエラーとなる.通常は常にオンラインなので問題はないが,持ち運びNotePCなどではオフラインオンラインが発生してメールの送信に失敗することがある.

$ echo 'hoge' | msmtp -a gmail matoken@gmail.com
msmtp: cannot locate host smtp.gmail.com: 名前またはサービスが不明です
msmtp: could not send mail (account gmail from /etc/msmtprc)

/usr/share/doc/msmtp/examples/ 以下の msmtpq 若しくは msmtpqueue に格納されているscriptを利用することでオフライン時にキューとして貯めておいてオンライン時に送信といったことが出来る.

どちらもsendmailと置き換えが可能なので,ネットワークダウン時に`/usr/sbin/sendmail`をこれに置き換えてオンライン時に戻してqueueをフラッシュするようにするといいかもしれない.

Debian/Ubuntuなら以下のあたりで,

  • /etc/network/if-down.d/
    /usr/sbin/sendmail を msmtpq or msmtpqueue に向ける

  • /etc/network/if-pre-up.d/
    /usr/sbin/sendmail を msmtp に向ける

  • /etc/network/if-up.d/
    queueをフラッシュ

NetworkManagerだと /etc/NetworkManager/dispatcher.d/ 以下で同じことが出来る.

msmtpq

圧縮されているmsmtpqを展開して実行権を付与する
$ sudo gunzip /usr/share/doc/msmtp/examples/msmtpq/msmtpq.gz
$ sudo chmod 755 /usr/share/doc/msmtp/examples/msmtpq/msmtpq
使いやすい場所にシンボリックリンクを張る
$ sudo ln -s /usr/share/doc/msmtp/examples/msmtpq/msmtpq /usr/local/bin/msmtpq
$ sudo ln -s /usr/share/doc/msmtp/examples/msmtpq/msmtp-queue /usr/local/bin/msmtp-queue
queueとlogディレクトリを作成
$ install -d -m 700 ~/.msmtp.queue
$ install -d -m 700 ~/log
オフライン時に送信しようとする
$ echo 'msmtpq' | msmtpq -C ~/.msmtprc -a gmail matoken@gmail.com
  mail for [ -C /home/matoken/.msmtprc -a gmail matoken@gmail.com ] : couldn't be sent - host not connected
  enqueued mail as : [ 2018-09-18-06.21.48 ] ( -C /home/matoken/.msmtprc -a gmail matoken@gmail.com ) : successful
queueを確認する
$ msmtp-queue -d

  mail  num=[ 1 ]  id=[ 2018-09-18-06.21.18 ]

  mail  num=[ 2 ]  id=[ 2018-09-18-06.21.48 ]
queueをフラッシュする
$ msmtp-queue -r
  mail [ 1 ] [ 2018-09-18-06.21.18 ] from queue ; send was successful ; purged from queue
  mail [ 2 ] [ 2018-09-18-06.21.48 ] from queue ; send was successful ; purged from queue
$ msmtp-queue -d

  no mail in queue

msmtpqueue

使いやすい場所にシンボリックリンクを張る
$ sudo ln -s /usr/share/doc/msmtp/examples/msmtpqueue/msmtp-enqueue.sh /usr/local/bin/msmtp-enqueue.sh
$ sudo ln -s /usr/share/doc/msmtp/examples/msmtpqueue/msmtp-listqueue.sh /usr/local/bin/msmtp-listqueue.sh
~$ sudo ln -s /usr/share/doc/msmtp/examples/msmtpqueue/msmtp-runqueue.sh /usr/local/bin/msmtp-runqueue.sh
`msmtp`コマンドの代わりに`msmtp-enqueue.sh`を使う
$ echo 'queue' | msmtp-enqueue.sh -C ~/.msmtprc -a gmail matoken@gmail.com
queueを確認する
$ msmtp-listqueue.sh
No mail in queue
今回のようにメールの内容がbodyだけでFrom, To, Subject が存在しないとこのscriptはうまく機能しない><
         egrep -s --colour -h '(^From:|^To:|^Subject:)' "$i" || echo "No mail in queue";
直接`~/.msmtpqueue/`を確認するとqueueが溜まっているのがわかる
$ ls -lA ~/.msmtpqueue/
合計 8
-rw------- 1 matoken matoken  7  9月 18 00:15 2018-09-18-00.15.53.mail
-rw------- 1 matoken matoken 53  9月 18 00:15 2018-09-18-00.15.53.msmtp
Subjectの付いたメールがある時
$ msmtp-listqueue.sh
No mail in queue

Subject: offline><
オンライン時にqueueをフラッシュする
$ msmtp-runqueue.sh
*** Sending 2018-09-18-00.15.53.mail to -C /home/matoken/.msmtprc -a gmail matoken@gmail.com ...
2018-09-18-00.15.53.mail sent successfully
*** Sending 2018-09-18-00.27.21.mail to -C /home/matoken/.msmtprc -a gmail matoken@gmail.com ...
2018-09-18-00.27.21.mail sent successfully

#sudoの場合も ~root/.msmtpqueue/ だった.

tips

gmailで以下のエラーとなった場合 tls_starttls on ( tls onのときの既定値? )と設定すると送信できた
$ echo "hello msmtp" | sudo msmtp -a gmail matohara@gmail.com
msmtp: envelope from address matohara@gmail.com not accepted by the server
msmtp: server message: 530 5.7.0 Must issue a STARTTLS command first. k126-v6sm14991126pgk.26 - gsmtp
msmtp: could not send mail (account gmail from /etc/msmtprc)
Yandexでメール送信時に帰ってこない場合 tls_starttls off と設定すると送信できた
niftyで以下のエラーとなった場合 tls_starttls off と設定すると送信できた
msmtp: network read error: 接続が相手からリセットされました
msmtp: could not send mail (account nifty from /etc/msmtprc)

試した環境

環境1(Raspberry Pi 2B/Raspbian stretch)
$ dpkg-query -W msmtp msmtp-mta gnupg2 openssl
gnupg2  2.1.18-8~deb9u2
msmtp   1.6.6-1
msmtp-mta       1.6.6-1
openssl 1.1.0f-3+deb9u2
$ lsb_release -d
Description:    Raspbian GNU/Linux 9.4 (stretch)
$ uname -m
armv7l
環境2(Ubuntu 18.04 LTS)
$ dpkg-query -W msmtp msmtp-mta gnupg2 openssl
gnupg2  2.2.4-1ubuntu1.1
msmtp   1.6.6-1
msmtp-mta       1.6.6-1
openssl 1.1.0g-2ubuntu4.1
$ lsb_release -d
Description:    Ubuntu 18.04.1 LTS
$ uname -m
x86_64
環境3(Debian sid)
$ dpkg-query -W msmtp msmtp-mta gnupg2 openssl
gnupg2  2.2.10-1
msmtp   1.6.7-1
msmtp-mta
openssl 1.1.1-1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

crontab から送信される電子メールの件名を指定したい

crontab で実行されたコマンドの出力はメールで送られますが,このときの件名は「Cron <ユーザ名@ホスト名> 実行コマンド」のようになります.

crontab 例
15 7 * * *  echo "cron subject"
メール例
Subject: Cron <matoken@T430s> echo "cron subject"

cron subject
1つのhostからこんなメール飛んで来るとどれがどれかわかりづらい
Cron <matoken@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……
Cron <root@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……
Cron <root@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……

分かりづらいので自分で件名を付けたいところです.

: を利用する

: は shell の組み込み関数で何もせず正常終了します.
コマンドなので # と違い,; の後にコマンドを書くとその後のコマンドは解釈されます.

$ :           #何もしない
$ : hoge
$ : echo hoge
$ : rm -rf *
$ : $(hostname)  #コマンドも展開せず何もしない
$ : `whoami`
$ : hoge; echo fuga   #;の後は解釈される
fuga
$ # hoge
$ # hoge; echo fuga

これをcrontabの頭に書くとこういう感じになります.

crontab
29 6 * * *  : cron subject; echo "hello"
mail
Subject: Cron <matoken@T430s> : cron subject; echo "hello"

hello

少しわかりやすくなりました.

mailコマンドを利用する

これはちょっと反則な感じがするのですが件名にコマンド実行結果を入れたり,頭の部分も書き換えたい場合はcronだけではできなさそうなのでmailコマンド経由で送信してみます.今回mailutilsのmailコマンドを利用しましたが,bsd-mailxやmutt等々ももちろん使えます.

crontab
45 6 * * *  echo "cron test" | mail -s "$(hostname)@$(whoami) cron Subject : $(date +\%F)" matoken+cron@example.com
mail
Subject: T430s@matoken cron Subject : 2018-09-13
X-Mailer: mail (GNU Mailutils 3.4)

cron test

mail コマンドの -s オプション部分が件名になります.その後ろが宛先のメールアドレス.bodyはcronの出力をパイプから受け取ります.

STDERR が別メールで届く

STDERR の出力があった場合cronでメールが送られてしまいます.mailコマンドと合わせて1度に2通届くことに.
実行コマンドの後ろに 2>&1 を付けて STDERR を STDOUT に渡してmailコマンドだけにします.

crontab
45 6 * * *  echo "cron test" 2>&1 | mail -s "$(hostname)@$(whoami) cron Subject : $(date +\%F)" matoken+cron@example.com

出力がなくてもメールが届く

crontab の場合コマンドの出力がなければメールが送られませんが,このコマンドでは NULL でもメールが送信されます.
未解決.

余録

cronで一切メールを送りたくない

場合crontabで MAILTO=”” を設定する
MAILTO=""

指定したコマンドだけメールを送りたくない

STDOUT と STDERR を /dev/null に捨てる
20 6 * * *  echo "cron subject" > /dev/null 2>&1

メールが届かない

/var/spool/mail/ユーザ名 のローカルにはメールがどとくけど,インターネット上のメールアドレスを指定しても届かない場合メールサーバの設定が出来ていないかもしれません.メールサーバ(sSMTP/msmtp等はデーモンが起動しないのでメールを受け取らず送信するだけならおすすめ)を設定してから再度試してみましょう.

環境1
$ man cron | grep -m1 cron
       cron - daemon to execute scheduled commands (Vixie Cron)
$ dpkg-query -W cron mailutils
cron    3.0pl1-128.1ubuntu1
mailutils       1:3.4-1
$ lsb_release -d
Description:    Ubuntu 18.04.1 LTS
$ uname -m
x86_64
環境2
$ man cron | grep -m1 cron
       cron - 予定されたコマンドを実行するデーモン(Vixie Cron)
$ dpkg-query -W cron mailutils
cron    3.0pl1-130
mailutils       1:3.4-1+b1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

Debian stretch で php5 / php7.0 を切り替え

update-alternatives で OK かなと思ったのですが,

$ sudo update-alternatives --config php
There are 2 choices for the alternative php (providing /usr/bin/php).

  Selection    Path             Priority   Status

--------------------

* 0            /usr/bin/php7.0   70        auto mode
  1            /usr/bin/php5     50        manual mode
  2            /usr/bin/php7.0   70        manual mode
  Press <enter> to keep the current choice[*], or type selection number: 0
$ php -v
PHP 7.0.30-0+deb9u1 (cli) (built: Jun 14 2018 13:50:25) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.30-0+deb9u1, Copyright (c) 1999-2017, by Zend Technologies

apache では php5 のままです.

$ w3m -dump http://localhost/phpinfo.php|grep -m1 'PHP Version'
PHP Version 5.6.30-0+deb8u1

apache module を切り替えたらokでした.

$ sudo a2dismod php5
$ sudo a2enmod php7.0
$ systemctl restart apache2
環境
$ dpkg-query -W apache2 php5 libapache2-mod-php5 php7.0 libapache2-mod-php7.0
apache2 2.4.25-3+deb9u5
libapache2-mod-php5     5.6.30+dfsg-0+deb8u1
libapache2-mod-php7.0   7.0.30-0+deb9u1
php5    5.6.30+dfsg-0+deb8u1
php7.0  7.0.30-0+deb9u1
$ lsb_release -d
Description:    Debian GNU/Linux 9.5 (stretch)
$ uname -m
x86_64

trash-cli で cli でもゴミ箱利用

rm コマンドはとても強力です.バックアップもなく誤って削除したファイルは復旧できない可能性が高いです.
そこで rm の alias に rm -i を指定して確認メッセージを出すなどしている環境もありますが,いつも使っていると手癖で即削除してしまったりして確実ではありません.GUI環境のファイラーなどではゴミ箱機能が使えて削除してもゴミ箱を空にするまで復元が可能です.
これをcuiでも利用できる trash-cli というツールがあります.デスクトップと共通(freedesktop.org trashcanと共通)のゴミ箱が使えて便利です.

削除してしまったファイルを復元したい場合なるべく早く削除したファイルシステムを umount or mount -o ro してファイル復元ツールを試してみるともしかしたら復元できるかもしれません.Debian の場合 forensics-all/forensics-extra pkg 等を覗いてみると様々なツールが見つかると思います.(例えばext3/ext4ファイルシステムでの復元ツールのextundeleteや汎用のscalpel等)

導入
$ sudo apt install trash-cli
$ dpkg -L trash-cli|grep bin/
/usr/bin/restore-trash
/usr/bin/trash
/usr/bin/trash-empty
/usr/bin/trash-list
/usr/bin/trash-put
/usr/bin/trash-rm
trash ゴミ箱に捨てる
$ touch hoge  #ファイル作成
$ trash hoge  #ファイルを捨てる
$ mkdir -p hoge/fuga/piyo #ディレクトリ作成
$ trash hoge  #ディレクトリを捨てる
trash-list ゴミ箱の中を見る(同じ場所同じ名前のファイルもそれぞれ管理される)
$ trash-list | grep hoge
2018-09-11 05:36:19 /home/matoken/tmp/hoge
2018-09-12 08:57:31 /home/matoken/tmp/hoge
2018-09-12 08:37:09 /home/matoken/tmp/hoge
2018-09-12 08:57:35 /home/matoken/tmp/hoge
2018-09-12 08:36:56 /home/matoken/tmp/hoge
2018-09-11 05:36:34 /home/matoken/tmp/hoge
trash-empty ゴミ箱を空にする
$ trash-empty
$ trash-list
restore-trash 対話的にファイルを復元する
$ restore-trash
   0 2018-09-14 05:15:11 /home/matoken/tmp/piyo
   1 2018-09-14 05:13:22 /home/matoken/tmp/hoge
   2 2018-09-14 05:15:11 /home/matoken/tmp/fuga
What file to restore [0..2]: 0  #復元したいファイルの番号を指定
trash を rm の alias にする(alias にてオプションを付与してオプションは無視するようになっている)
$ alias rm='trash'
$ rm hoge
$ rm -rf dir

という感じで簡単に使えます.sudo を使うことも可能です.ゴミ箱の実体は環境によりますが,手元の環境では ~/.local/share/Trash/ 以下でした.このあたりは以下のページが参考になると思います.

ゴミ箱を空にしないとどんどんファイルは溜まっていきます.autotrash を使って掃除するのがおすすめです.

<追記>

Google+のコメントでmasakaさんに教えてもらったのですが,trash-empty 日付 と日付を指定することで日付以上の日数が経過したファイルが削除できるようです.日付指定だけならautotrash を導入しなくてもいいですね.

Masakazu Takahashi

ちなみにtrash-cliでも`trash-empty 30`とか実行すると、削除して30日超のファイルをゴミ箱から消してくれます。

man trash-emptyより
ARGUMENTS
       To remove all trashed files, use 'emtpy-trash'.

       To remove files that have been in the trash more than a given number of
              days, use 'trash-empty x', 'x' representing the number of days.

</追記>

環境
$ dpkg-query -W trash-cli
trash-cli       0.12.9.14-2.1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

#trash-cli は現在 0.17.1.14 で 0.12.9.14 のリリース日は 15 Sep 2012 となっている.

autotrash でゴミ箱を自動清掃

ゴミ箱は便利ですがどんどん溜まっていくので定期的に捨てないといけません.気が向いたときにゴミ箱を空にするのでもいいのですがそれだと1月前にゴミ箱に入れて確実にゴミであろうファイルもさっきゴミ箱に入れたもしかしたら誤って削除したファイルも一緒に消すことになってしまい心配です.
autotrashを使うとゴミ箱に入れた日数やファイル名,空き容量が何GBより少なくなったなどの様々な条件によりゴミ箱内のファイルを削除することができます.crontabに登録しておくと自動化もできてお薦めです.

※以下はmanのexampleで日本語部分は間違っているかもしれません –dry-run と –verbose オプションを付けて動作確認をした上で使うようにしてください.

30日以上経過したファイルを削除
autotrash -d 30
          Purge any file that has been in the trash for more then 30 days.
ゴミ箱のファイルシステムの空き容量が1024MB(1GB)以下になるようファイルを削除.削除する場合30日以上経過したファイルが対象?
autotrash --max-free 1024 -d 30
          Only purge files from the trash if there is less than 1GB of space left on the trash filesystem. If so, only trash files that are older than 30 days.
ゴミ箱のファイルシステムの空き容量が2048MB(2GB)以下になるまで古いファイルから削除する?
autotrash --min-free 2048
          Purge files from trash, oldest first, till there is at least 2GB of space on the trash filesystem. There is no restriction on how old trashed files are.
ゴミ箱のファイルシステムの空き容量が2048MB(2GB)以下になるまでファイルを削除する.削除する場合はまず”*.bak”を削除して次に”\*.avi”その後は古いファイルから削除する?
autotrash --min-free 2048 -D '.*\.bak' -D '.*\.avi'
          Purge files from trash till there is at least 2GB of space on the trash filesystem. If we need to remove files, make sure we remove *.bak files first, then
          all *.avi files and after that the oldest to the newest. There is no restriction on how old trashed files can get. Please note that '.*\.bak' and '.*\.avi'
          are regular expressions and not glob patterns. Given that they are regular expressions, using -D '.*\.(png|gif|jpg|jpeg)' will match images with any of the
          given extensions.
ゴミ箱の容量が4000MBになるまでは何もしない,それ以上の場合は30日以上経過したファイルを削除し,ゴミ箱の容量が2048MB以下になるまで古いファイルから削除する?
autotrash --max-free 4000 --min-free 2048 -d 30
          Start  reading  the  trash  if there is less than 4000MB of free space, then start keeping an eye on. At that point, remove files older than 30 days and if
          there is less than 2GB of free space after that remove even newer files.

私は単純にゴミ箱に入れて33日経ったファイルを削除するようにしています.
この例では毎日02:08に優先度を下げて実行しています.vixie-cronの場合 @daily でもいいし, @reboot でシステム起動時に処理とかでもいいかもしれません.詳細は man 5 crontab を参照してください.

$ crontab -l|grep autotrash
8 2 * * *       nice -n 19 ionice -c 3 autotrash -d 33

ただ,これはゴミ箱を使っているユーザ毎に設定しないといけないのがちょっと面倒です.一人で使っているシステムならいいのですが,利用者が1000人だと /etc/crontab に1000行書くなどしないといけません.
autotrash 0.2.1 では -t オプションで全ユーザのチェックが出来るようです.(手元の環境では 0.1.5 なので未確認)

You can also make autotrash process all user trash directories (not just in your home directory) by adding this crontab entry:

@daily /usr/bin/autotrash -td 30
環境
$ dpkg-query -W autotrash
autotrash       0.1.5-1.1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

#sidだけどupstreamに追従してないですね><

KeePassXC の Steam TOTP を試す

Steam ガードというスマートフォンアプリを使ったValve独自TOTPな多要素認証があります.これは通常のTOTP(rfc6238)と違い独自実装で数字だけではなくアルファベットも利用しているのでOATH ToolkitやGoogle Authenticatorでは認証できません.

Steam ガードのTOTPはValve独自ですが一応いくつかの実装はあります.(未検証)

KeepassXC にも TOTP(KeePassXC 2.2.0以降)と Steam ガードの TOTP(KeePassXC 2.3.0以降)がサポートされています.今回これを試してみました.

a generator for time-based one-time passwords (TOTP)
Add support for Steam one-time passwords [#1206]

しかし,これらを試すにはSteam Guard Mobile Authenticatorを設定したスマートフォンの中からTOTPの秘密鍵を入手する必要があります.以前のAndroidではadb backup するだけで鍵の書かれたファイルが入手できていたらしいのですが現在は暗号化されていてこの手順では入手できないようです.
GitHubにAPKにpatchするscriptが公開されていたのでまずはこれを試してみました.

これがうまく行けば以前のようにadb backupが出来るようになるはずです.しかし,バージョンの問題か失敗しました.

別の方法としてAndroidのroot取得済み端末にSteam Guard Mobile Authenticatorを導入してこちらの端末を有効にして秘密鍵を取得しました.

rooted端末から設定ファイルを抜き出してトークン取得
$ adb shell #Android shellを起動してファイル名を確認
1|shell@MK16i:/ $ su
root@MK16i:/ # ls -l /data/data/com.valvesoftware.android.steam.community/files/
-rw-rw---- u0_a59   u0_a59        448 2018-08-31 22:25 Steamguard-76561198085918260
root@MK16i:/ # exit
root@MK16i:/ $ exit #AndroidからexitしてPCに戻る
$ adb root  #rootになる
$ adb pull /data/data/com.valvesoftware.android.steam.community/files/Steamguard-76561198085918260  #ファイル取得
$ adb kill-server  #adb server終了
$ file Steamguard-76561198085918260
Steamguard-76561198085918260: ASCII text, with very long lines, with no line terminators
$ lv Steamguard-76561198085918260
$ jq .uri Steamguard-76561198085918260 | sed -e 's/^.*=\(.*\)&.*$/\1/'  #鍵表示
OXYBZQLEOB7KKFAPERMN8EGNOLJWEDYZ
$ shred -uz Steamguard-76561198085918260  #ファイル消去

取得した鍵をKeePassXCに登録してみます.
Steamの設定上で右クリック,「タイムベースワンタイムパスワード」→「TOTP の設定…」から「キー」に設定します.
登録した後Steamの設定上で右クリック,「タイムベースワンタイムパスワード」→「TOTP を表示」でトークンが表示できます.
29467671377 1a01b3ce35

Androidスマートフォンアプリと見比べてみると同じトークンが表示され,Steamにもloginできます :)

43687930524 4260e0f2a6

[

Steam Guard Mobile Authenticatorは同時に1端末しか登録できず,2台目を設定すると1台目の端末の鍵が無効にされます.なのでKeePassXCを利用する場合はroot端末と併用するか,root端末から消してKeePassXCのみで運用するしかなさそうです.

複数の携帯電話で Steam アカウントを認証できますか?
いいえ、ひとつのアカウントで一度に有効化できる認証機器はひとつだけです。

もう一つ問題が.KeePassXCにはcli版が同梱されているのですが,バージョン2.3.4時点ではTOTPのオプションが見当たりません.GUIのみの利用となりそうです.

$ keepassxc-cli -h
Usage: keepassxc-cli [options] command
KeePassXC command line interface.

Available commands:
add            Add a new entry to a database.
clip           Copy an entry's password to the clipboard.
diceware       Generate a new random diceware passphrase.
edit           Edit an entry.
estimate       Estimate the entropy of a password.
extract        Extract and print the content of a database.
generate       Generate a new random password.
locate         Find entries quickly.
ls             List database entries.
merge          Merge two databases.
rm             Remove an entry from the database.
show           Show an entry's information.


Options:
  -h, --help     Displays this help.
  -v, --version  Displays version information.

Arguments:
  command        Name of the command to execute.
$ keepassxc-cli -v
2.3.4
環境
$ dpkg-query -W keepassxc
keepassxc       2.3.4+dfsg.1-1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

Google Chrome 69 でURLのサブドメインが表示されなくなったのを表示する

<追記>
69.0.3497.92 で修正された

chrome://flags/#omnibox-ui-hide-steady-state-url-scheme-and-subdomains を「Default」に戻してもサブドメインが省略されないのを確認 :)
</追記>

Google Chrome 69 で アドレスバーの表示が変わりました.例えば www.matoken.org で www が見えなくなり,matoken.org と表示されるようになりました.
更に,www.hoge.www.matoken.org は hoge.matoken.org に見えるというおそらくバグであろう挙動も><

42739367390 9acbb565de

Workaround として,chrome://flags/#omnibox-ui-hide-steady-state-url-scheme-and-subdomains を Disabled にすると以前の挙動になります.

30678044578 41d01a41ff

Chromium 69.0.3497.81-3 は既定値で以前と同じ動作のようです.

環境
$ dpkg-query -W google-chrome-stable chromium
chromium        69.0.3497.81-3
google-chrome-stable    69.0.3497.81-1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

Google Chrome からエクスポートしたパスワードリストを KeepassXC にインポート

人に説明するのに手元で試したのですがせっかくなのでblogに

Google Chrome のパスワードマネージャは使っているけれど,汎用的なKeepassXC に移行なメモです.

Google Chrome からパスワードのエクスポート

「設定」→「パスワードとフォーム」→「パスワードを管理」
若しくは chrome://settings/passwords にアクセス.

「︙」を押して「パスワードをエクスポート」から「パスワードをエクスポート…」から適当な場所にパスワードを保存します.

42595980870 d5446a65ee

30536920508 8d62cb50bd

KeepassXC へのインポート

KeepassXC を起動して,「CSVからインポート」を選びます.

43503758335 aa7e31c143

列のレイアウトを以下のようにしてインポートします.

  • Title : 列1

  • Username : 列3

  • Password : 列4

  • URL : 列2

44404975011 57f063d488

ウェブブラウザへの拡張機能の導入

利用するウェブブラウザに拡張機能を導入する.

KeepassXC の「ツール」→「設定」の「ブラウザー統合」で利用するウェブブラウザを有効にする.

42603172110 1770a7e23f

後はよしなに.

環境
$ dpkg-query -W keepassxc google-chrome-stable
google-chrome-stable    68.0.3440.106-1
keepassxc       2.3.1+dfsg.1-1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64

DNSキャッシュサーバなアドブロッカーのPi-holeを試す

2018-08-18 の鹿児島Linux勉強会 2018.08 で発表したものに加筆修正したもの.

アドブロッカー?

  • 広告をブロック

  • ブラウザの拡張機能などで実現するのが一般的(重い&ブラウザ毎に設定が必要)

    • uBlock Origin

    • プライベートブラウジングモードでは(基本的に)利用できない

  • スマートフォンは?

    • rootなどが必要(ウェブブラウジングは拡張機能や広告ブロック機能のあるウェブブラウザなどで回避可能)

Pi-hole

29084865297 4f02afec31

  • DNSキャッシュサーバとして動作して広告をDNSベースでブロック

    • PC側では設定不要 or DNS設定のみ

    • 軽い

  • Webベースの管理画面が利用可能

  • DNS以外にDHCPサーバ機能も利用可能

動作要件

名前にPiとついているし事例が多いがRaspberry Pi以外でも動作する

Hardware
Pi-hole is very lightweight as it only handles DNS queries and returns a blank HTML file so it doesn’t need much processing power.

~52MB of free space
512 MB RAM
Software
Pi-hole will run on most Debian-based distro’s and is the preferred platform for it.

We officially support the following:

Raspbian: Jessie/Stretch
Ubuntu: 16.04 / 16.10
Debian: 8 / 9
Fedora 26
CentOS: 7 (not ARM)

導入例

お手軽なインストールscriptが用意されている
公式ページでは,

curl -sSL https://install.pi-hole.net | bash

とはいえ怖いので,こんな感じで入れた

$ wget -O basic-install.sh https://install.pi-hole.net
$ lv basic-install.sh
$ sudo porg -lp pi-hole bash ./basic-install.sh
  • インストーラはTUIでいくつかの選択肢が表示される

  • 設定はこのあたりに/etc/pihole/setupVars.conf

  • アンストーラーもついているが,パッケージ周りとか面倒(導入済みだったかどうか関係なく関連パッケージを1つづつ確認しないといけない)なのでchroot環境などで試したほうが良い

44003211731 7da5e55b53

DNSの選択

  • Public DNS各種もしくはCustomから任意のDNSが指定可能

  • 今回は自分の家のUnboundを指定

  • 必要なパッケージは自動で導入される

43284561304 664a4c6675
44003212211 af3c239901

ad listの選択

43284561514 57f8f88c59

Protocolの選択

44003212531 6105935e3a

Web管理画面有効無効

43284561704 abff464168
44003212851 7e3c626b79

ログ

43284561874 54e4f14dbd

インストール完了

この画面はメモしておきましょう

44003213001 bbcd67ffcd

もしパスワードを忘れたら

$ pihole -a -p
Enter New Password (Blank for no password):
Confirm Password:
  [✓] New password set

端末のDNSをPi-holeに向けて試す(adhoc)

ネットワークのDNSをPi-holeのipにします

nm-applet

42224130270 b14c28b364

/etc/resolv.conf
nameserver 192.168.2.211

ネットワーク全体に反映

  • DHCPサーバからリリースされるDNS情報をPi-holeのものに差し替える

or

  • DHCPサーバをPi-holeに切り替える

    • Pi-holeのDHCPDは管理画面のSettings → DHCPから有効にできる

から有効にできる

VPN の nameserver に指定

自分は外では VPN を使うが,そのときこの nameserver を指定すると携帯回線でもパケットの消費が抑えられる効果もある

DNSが切り替わったか確認

確認例
$ dig example.com|grep -i server
;; SERVER: 192.168.2.211#53(192.168.2.211)

管理画面

ダッシュボード

43115604235 f07c9c9060

log

43973290462 5af9c902d5

システム情報

29084598777 90979e5772

広告ブロックリスト管理

43303343644 0e3b2de779

DNS設定

30153543558 3e368f177f

DHCP設定

30153549218 78f1098ff5

API/Web管理画面設定

42212991130 cc6ea1e357

プライバシー設定

43973382062 ca95d2fd21

テレポーター(設定のインポートエクスポート)

43973387132 fed8d96213

ログからホワイトリストブラックリストに

ログからドメインをホワイトリスト,ブラックリストに移動できる

43301172114 e220a2a2bc
43113907005 3561309f64

WebIFはoption

pihole commandが存在する

help
$ pihole --help
Usage: pihole [options]
Example: 'pihole -w -h'
Add '-h' after specific commands for more information on usage

Whitelist/Blacklist Options:
  -w, whitelist       Whitelist domain(s)
  -b, blacklist       Blacklist domain(s)
  --wild, wildcard     Wildcard blacklist domain(s)
  --regex, regex       Regex blacklist domains(s)
                        Add '-h' for more info on whitelist/blacklist usage

Debugging Options:
  -d, debug           Start a debugging session
                        Add '-a' to enable automated debugging
  -f, flush           Flush the Pi-hole log
  -r, reconfigure     Reconfigure or Repair Pi-hole subsystems
  -t, tail            View the live output of the Pi-hole log

Options:
  -a, admin           Web interface options
                        Add '-h' for more info on Web Interface usage
  -c, chronometer     Calculates stats and displays to an LCD
                        Add '-h' for more info on chronometer usage
  -g, updateGravity   Update the list of ad-serving domains
  -h, --help, help    Show this help dialog
  -l, logging         Specify whether the Pi-hole log should be used
                        Add '-h' for more info on logging usage
  -q, query           Query the adlists for a specified domain
                        Add '-h' for more info on query usage
  -up, updatePihole   Update Pi-hole subsystems
                        Add '--check-only' to exit script before update is performed.
  -v, version         Show installed versions of Pi-hole, Web Interface & FTL
                        Add '-h' for more info on version usage
  uninstall           Uninstall Pi-hole from your system
  status              Display the running status of Pi-hole subsystems
  enable              Enable Pi-hole subsystems
  disable             Disable Pi-hole subsystems
                        Add '-h' for more info on disable usage
  restartdns          Restart Pi-hole subsystems
  checkout            Switch Pi-hole subsystems to a different Github branch
                        Add '-h' for more info on checkout usage

Pi-hole アップデートの確認とアップデート

Pi-holeのアップデート確認
$ pihole -up --check-only
[i] Checking for updates...
[i] Pi-hole Core: up to date
[i] Web Interface: up to date
[i] FTL: up to date
[] Everything is up to date!
Pi-holeのアップデート
$ pihole -up
広告ドメインリストの更新
$ pihole updateGravity
  [i] Neutrino emissions detected...
  [✓] Pulling blocklist source list into range

  [i] Target: raw.githubusercontent.com (hosts)
  [✓] Status: Retrieval successful

  [i] Target: mirror1.malwaredomains.com (justdomains)
  [✓] Status: No changes detected

  [i] Target: sysctl.org (hosts)
  [✓] Status: No changes detected

  [i] Target: zeustracker.abuse.ch (blocklist.php?download=domainblocklist)
  [✓] Status: No changes detected

  [i] Target: s3.amazonaws.com (simple_tracking.txt)
  [✓] Status: No changes detected

  [i] Target: s3.amazonaws.com (simple_ad.txt)
  [✓] Status: No changes detected

  [i] Target: hosts-file.net (ad_servers.txt)
  [✓] Status: No changes detected

  [✓] Consolidating blocklists
  [✓] Extracting domains from blocklists
  [i] Number of domains being pulled in by gravity: 157918
  [✓] Removing duplicate domains
  [i] Number of unique domains trapped in the Event Horizon: 134681
  [i] Number of whitelisted domains: 0
  [i] Number of blacklisted domains: 0
  [i] Number of regex filters: 0
  [✓] Parsing domains into hosts format
  [✓] Cleaning up stray matter

  [✓] Force-reloading DNS service
  [✓] DNS service is running
  [✓] Pi-hole blocking is Enabled
crontabに登録
# Pi-hole広告ドメインリスト更新
7 3 * * * pihole updateGravity | tee >$(telegram-msg-cron)
# Pi-hole アップデートチェック
11 3 * * *      if [ $(pihole -up --check-only|tail -1|grep -c 'Everything is up to date!') ]; then echo ''; else echo "${HOSTNAME} : please Pi-hole update!" | tee >$(telegram-msg-cron) ; fi

日本向け広告リストを追加してみる

$ echo 'https://280blocker.net/files/280blocker_host.txt' | sudo tee -a /etc/pihole/adlists.list
https://280blocker.net/files/280blocker_host.txt
$ pihole -g

検索すると様々なドメインリストが存在する.用途に合わせて登録すると良さそう.

Pi-hole メリット,デメリット

  • メリット

    • 軽量で動作要件も低い

    • DNSベースなのでスマートフォンなどでもOK!(アプリ内の広告ブロックも)

    • ウェブブラウザの場合でも端末やブラウザ毎に個別に設定する必要がない

    • 設定も簡単で動作も管理画面で確認しやすい

    • 転送量も減る

  • デメリット

    • uBlock Originに比べると広告のブロック率が低い?(見ているsiteにも依るかも)

      • 拡張性があるので好みのリストを追加すれば良さそう

    • 今見えている広告をブロックしたいといったときにはブラウザの拡張機能のほうが便利

    • 広告の動きを確認するにはDNSを切り替える必要があり面倒

      • nm-appletだとPi-holeと通常DNSの設定をそれぞれ作っておくとワンタッチで切り替えられて便利
        43127431915 f050327120

        • PC → Pi-hole → Unbound → ISP

        • PC → Unbound → ISP

      • Wi-Fi AP を Pi-hole 利用とそうでないものの2つ用意する

家庭や小規模ネットワーク向け?

別解

Pi-holeのad listをそのままor整形して/etc/hostsに突っ込めばとりあえずblockできる
(UnboundやDnsmasqとかに入れても)

ad list
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://mirror1.malwaredomains.com/files/justdomains
http://sysctl.org/cameleon/hosts
https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist
https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt
https://hosts-file.net/ad_servers.txt
listの内容
$ wget -q -O - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts | lv
  :
0.0.0.0 1493361689.rsc.cdn77.org
0.0.0.0 30-day-change.com
0.0.0.0 2468.go2cloud.org
0.0.0.0 adservice.google.nl
0.0.0.0 adsmws.cloudapp.net
  :
$ wget -q -O - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts|lv
amazon.co.uk.security-check.ga
autosegurancabrasil.com
dadossolicitado-antendimento.sad879.mobi
hitnrun.com.my
maruthorvattomsrianjaneyatemple.org
  :

別解?

ウェブブラウジング時に広告だけでなくトラッキングなども考慮
このあたりはこまめに設定が必要なので一括管理は難しそう

Pi-hole

  • 導入が簡単

  • リソース少なめ

  • 管理画面がわかりやすい

  • 家庭や小規模ネットワーク向け?

QA

*BSDとかでは動かせない?

パッケージの確認と導入周りとネットワーク設定あたりを合わせればいけるのでは?
でもhostsやUnboundなどで設定したほうがきっと楽

広告がdomainではなくipで配信されるようになったら?

ipアドレスを Pi-hole の Block list に登録してみたら登録できた.しかしブロックはできなかった.iptablesなどでブロックする感じ?