モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

介護ハッカソン長野に参加

これ書いてるのすでに2月末なのですが、2/1(土)に介護ハッカソン長野に参加させていただきました。

www.kaigohackathon-nagano.com

介護ハッカソンとは、介護系の方とコンピュータ系のエンジニアがチームになって、介護現場での問題をWeb技術やIoT等を利用して改善するのを競い合うハッカソンです。

2回開催され、3/7(土)の2回目のときにチームの発表を行って、審査と優勝者が決まことになっていました。
が、この新型コロナの問題で、2回目はチームで一人のみが代表で参加して発表、ということになりました。

このハッカソンは元々、9月にやる予定だったのが台風のため延期になってこの日程だったので、開催に関わられた皆さんは色々とほんとに大変だったと思います。

ハッカソンでは、介護系の方に意見を聞きながら、アジャイル勉強会でやったように考えをポストイットに書いてホワイトボードにぺたぺた張っていきまとめていく、というようなことでアイデア出しと意見の整理を行いました。
この辺は、勉強会でやったことがそのまま活かせてとてもよかったと思います。
さらに、出てきたアイデアも他とちょっとひねった感じになっていて、良いのでは、と思っています。

Ubuntuでiptablesの設定を永続化したつもりでハマる

Ubuntu 18.04 LTS を利用しているサーバがあり、そこでiptablesの設定がしてありました。

Ubuntuだとiptablesの設定はそのままではなぜか保存がされず、iptables-persistentを入れないと永続化ができないとなっています。
で、下記サイトのように

Ubuntuでiptablesの設定をiptables-persistentで永続化する

Ubuntu 18.04 LTS iptables Fail2ban 設定等 | ひかるLOG

iptables-persistentを入れて

/etc/iptables/rules.v4

に設定を書いて永続化ができたつもり、でいました。

が、サーバメンテでリブート後DNSの通信が通らなくなり、確認したところiptablesの設定が以前のものに戻ってしまっていて止めていました。

iptables-persistentの設定例を見ると /etc/iptables/rules.v4 (と rules.v6)に設定を書くとなっているのですが、実は /etc/iptables 以下に

/etc/iptables/iptables.rules

というファイルが元々ありました。

自分はこれがあっても rules.v4 ファイルが有ればそちらが使われると思っていたのですが、この設定ファイルがあるとこちらのほうが優先して使われてしまうようです。

とりあえずこのファイルをリネームすることで解決しました。

PostfixでOpenSSLのバージョンでwarningが出る

古いCentOSに入っているTLS1.2対応したPostfixが、下記のような warning をずっと出していて大丈夫なのか、どうすれば止まるのか、という相談をうけました。

warning: run-time library vs. compile-time header version mismatch: OpenSSL 1.0.2 may not be compatible with OpenSSL 0.9.8

調べてみると、src/tls/tls_misc.c 中の tls_check_version 関数でこのwarningを出しており、OPENSSL_VERSION_NUMBER と SSLeay() の間でバージョンの違いがあると出るようでした。

そこで OPENSSL_VERSION_NUMBER を確認すると

/usr/include/openssl/opensslv.h

#define OPENSSL_VERSION_NUMBER       0x0090802fL

の設定が使われており、後からソースで入れたOpenSSLのバージョンと合っていないためとわかりました。

Postfixインストール時には下記オプションつけて

-L/opt/openssl/lib

後から入れたOpenSSLライブラリ指定していたのですが、include については指定されていなかったようです。

そこで include についても下記のように、後から入れたOpenSSLの include を参照するように追加してもらいました。

-I/opt/openssl/include

これで warning がでなくなりました。

NSEG勉強会で3件LTしました

もうひと月以上経ってしまったのですが、勉強会は報告エントリ書くまでが勉強会!ということで今更ながら書きます。

NSEG 19/08 フリープレゼン会 - connpass

久しぶりにNSEGの勉強会が開催され、このままでは@hATrayfloodさんが死んでしまう!と思っていくつかネタを考えていたら、結局3件ともLTやることになりました。

の3本です!

どれも20分のLTなので内容は浅めです。

milter-managerの話はもっと色々と説明すべき内容があるのにLT用にだいぶ短くしてしまっているので、今後ブログのエントリで詳しく書きたいと思っています。

今回、ひさしぶりにNSEG開催されたんですが、やっぱもうちょっと頻度保つようにできたらなと思いました。 とりあえず平日夜会を再開したいと思ってます。

@hATrayfloodさんの発表内容が、すんごい大変そうな話で、なぜこんな苦行をやってるんだろう… なんかの修行なんだろうか?と思って聞いてたんですが、終わってから後から気が付いたのですが、スマホだと拡張機能とか使えないから、ブラウザに機能追加したいと思ったら、自前ビルドで機能追加するしかないのでこんな話になるのですね。 この仕事はしんどすぎる… と思いました。

GmailアプリでのPOPメール送受信は直接行われている

自分の認識が誤ってたのでメモ。

AndroidGmailアプリから、ISPのメール送受信を行うためにPOPアカウントの設定が出来るが、これは普通にPCのメールソフトと同様、Gmailアプリから直接POP/SMTPが呼ばれてメールが送受されるようになっています。

これ、当たり前じゃん?と思われる人も多いと思うのですが、昔のGmailアプリではそれが出来ず、WebのGmail設定でPOP/SMTPの設定をしておいて使うようになっていました。
つまり、Gmail経由でPOPやSMTPが呼ばれるようになっていたため、接続元IPもgoogleになっていたのです。

なんかずっとその認識でいたのですが、Gmailアプリからの接続のログ見てたら、直接キャリアIPから接続しているようになっていたため、あれっ?と思って実験して確かめてしまいました。
ちゃんと知識をアップデートしていかないとダメですね。

「logits」の意味について

最近DeepLab v3+のことを調べていて、所々で「logits」という言葉が出てくるのですが、これの意味するところがよくわからない状況でした。

twitterで質問してみたところ、Higuchiさんから下記のように教えていただきました。

hinaser.github.io

TensorFlow等の機械学習フレームワークでは、これから確率に変換しようとしている出力層のニューロンの出力値を よくロジットと呼ぶことが多い。

最終レイヤーでは出力をシグモイド関数掛けてさらにソフトマックス掛けて確率として出力することが多いですが、その前のナマの値を「logits」と呼んでるということでした。

最終レイヤーの出力時の処理がシグモイド関数だけなら、その逆関数がlogitsだから、その前の値をさしてlogitsと呼ぶのも理解できます。

こういう慣習的な呼び方はぐぐってもあまり出てこないのがむつかしいところ。

メールアカウント盗られてこっそり受信されている例が結構ある話

ここのところサブミッションスパムが出されることが一定の頻度で続いていて最悪なのですが、そのことを調べていた時にちょっとイヤな例を見つけました。

サブミッションスパムで使われたアカウントがあり、ふとそのアカウントでメールの受信は来てるのかな?と確認しました。
すると、日本国内からのアクセスはないのに mail.ru ドメインからのアクセスがだいたい1時間に1回と定期的に来ていたのを見つけました。

mail.ru はロシアでメールサービスやっているところのドメインで、VPSのようなサービスもやっているところです。
なのでそこのWebメールサービスにアカウントが登録されていて、そこから受信が行われている、という可能性は考えられます。

ですが、その接続があった付近のIPで検索すると、他にも同様にアクセスされているアカウントがいくつもありました。
そしてそのうち一つは、その少し前にサブミッションスパムが出されていたものでした。
アカウント数を数えてみると、これまでサブミッションスパムで利用されてしまったよりも数倍多くありました。

あくまで状況証拠からですが、クラックされたアカウントが定期的に受信がされている、と考えるのが自然と思います。

状況まとめると

  • 外部からこっそり受信のみが行われているアカウントが結構ある
  • それらは1時間に1度くらいの頻度でメールが覗かれている

となります。

つまり、アカウント情報のもれたメールアカウントのメールを監視している大規模なネットワークが存在しているということなのです。

例えば、アカウント設定の再送をメールで行ったりしたのをフックして、そのアカウントも盗ってしまうとか、そういうのを自動でやってるのかなあ、と想像します。

これのなにが恐ろしいって、メール受信されていることをユーザは全く感知できない、ということです。

これ、大手ISPなんかだと、GoogleやLINEみたいに、普段の接続ではないIPからメール受信されました、みたいなアラート上げたりしてるんだろうか…?

こういうのって最近のセキュリティ界隈では結構知られていることなのでしょうかね?

(追記)

mail.ruのPOPしてくるIPからであること確認できたので、mail.ruに受信確認の設定がされているのだと思います。

またスマホから一つのメールアプリでまとめて読むために、mail.ruを使われる需要が結構あるようで、それように普通に設定していた可能性も高いです。

ただ、サブミッションスパムで利用されたアカウントとの重複率がだいぶ高いため、なんらかの理由で相関があるのだと思います。

例えば、そのようなユーザは他にもmail.ruのようなメール一括受信アプリを試している場合が多く、そこから漏れた or アカウント取得を主目的としたマルウェアを使ってしまった、などです。

このあたりは完全にこう、というのは結論づけることはできなそうですが。

Colabでshellを利用する

Google Colabを普通に使っているぶんには、例えばpip使ってなにかいれるような場合でも「!pip …」みたいにしてノート上で作業すれば良いのですが、なにかディープラーニング系のアプリケーションを入れて試すような場合だと、shellが使いたい… となることがあると思います。

そういう時にターミナルの画面出せるような方法ないのかな?と探したのですが、普通には出来ないのですね。

でそれを、ngrokを使って無理やりターミナルで繋げる方法が紹介されていました。

stackoverflow.com

ngrok経由でsshdに接続できるようにする

import random, string, urllib.request, json, getpass

#Generate root password
password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(20))

#Download ngrok
! wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
! unzip -qq -n ngrok-stable-linux-amd64.zip

#Setup sshd
! apt-get install -qq -o=Dpkg::Use-Pty=0 openssh-server pwgen > /dev/null

#Set root password
! echo root:$password | chpasswd
! mkdir -p /var/run/sshd
! echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
! echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
! echo "LD_LIBRARY_PATH=/usr/lib64-nvidia" >> /root/.bashrc
! echo "export LD_LIBRARY_PATH" >> /root/.bashrc

#Run sshd
get_ipython().system_raw('/usr/sbin/sshd -D &')

ngrokに接続するための認証とsshパスワードの取得

#Ask token
print("Copy authtoken from https://dashboard.ngrok.com/auth")
authtoken = getpass.getpass()

#Create tunnel
get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')

#Get public address and print connect command
with urllib.request.urlopen('http://localhost:4040/api/tunnels') as response:
  data = json.loads(response.read().decode())
  (host, port) = data['tunnels'][0]['public_url'][6:].split(':')
  print(f'SSH command: ssh -p{port} root@{host}')

#Print root password
print(f'Root password: {password}')

で、これで繋げられるようになるのですが、ちょっと目を離しているすきにすぐ切れてしまうため、screenとかを導入しといたほうが良いと思います。

ちなみにそれらの設定するための /root/.profile や /root/.screenrc などの設定ファイルは、

qiita.com

こちらで紹介されている「%%writefile」を使って書いとくと良いです。

長野ディープラーニング同好会 #14

長野ディープラーニング同好会14回めを開催しました。

長野ディープラーニング同好会 #14

自分が来年度の平日夜動けなくなる可能性があり、一旦休止するかもということで、これまでのまとめの意味もふくめて、簡単なコンペみたいなのをやってみました。

CIFAR10の認識をColabで10分だけ学習させて、テストデータでの認識率が一番高かった人の優勝、みたいなものです。
現代のCNNの直接の祖先であるLeNetをベースラインとして、そこから各種手法を取り入れていってどこまで上げられるか、という感じに行いました。
論文等ぐぐればCIFAR10認識のSoTA手法が出てくると思うのですが、そこはColab環境で「10分だけの学習時間」というしばりがあるため、例えば単純にネットワークを大きくすればいいとはならないわけです。

ただ、いきなりなにもない状況からだとみな書けないと思うので、下記のようにサンプルとなるコードを用意しました。

https://github.com/stealthinu/naganodeeplearningclub/blob/master/cifar10_10min.ipynb

最初は、非常に簡単にですが各手法がどういうことやっていてどんなメリット・デメリットが有るのかをざっと説明しました。
そこから各種手法を入れたり、パラメータを調節して認識率を上げてもらうようにしていただきました。

結局、ベースラインの70%に対し、80%の認識率になった方が一番になりました。

次回はどうなるかわかりませんが、とりあえずもう一度、2年前にやったディープラーニングハンズオンみたいなことをやれたらいいな、と考えています。

chroot環境で動くapache 2.4でCGIがPermission deniedになる問題

CentOS7 で chroot 環境で動く apache 2.4 の設定で、CGIがうまく動かないという相談を受けました。

apache 2.4 では mod_cgi ではなく mod_cgid を使うのですが、

[cgid:error] (13)Permission denied: [client *****] AH01257: unable to connect to cgi daemon after multiple tries: *****

のような感じのエラーが出て動かないという状況でした。

mod_cgid の設定は下記のようになっていました。

LoadModule cgid_module modules/mod_cgid.so

<IfModule cgid_module>
    Scriptsock /var/run/cgid/cgisock
</IfModule>

ここで「/var/run/cgid/」は chroot 環境のディレクトリに作られていて、パーミッションも与えられていて、実際 cgisock ファイルも apache が作成できている状況でした。

で実はこの「Scriptsock /var/run/cgid/cgisock」の指定のところ、よくあるのは「Scriptsock cgisock」のようにフルパスではなく書かれているのですが、この指定だと log ディレクトリ内に sgisock ファイルが作られてしまうため、このようにフルパスでの指定になっていました。

パーミッションについて色々試してもダメだったため、下記のように「Scriptsock /var/run/cgid/cgisock」を「Scriptsock cgisock」に修正して(もちろんディレクトリのパーミッションやオーナーは同じ設定)動かしたところ、無事に動くようになりました。

LoadModule cgid_module modules/mod_cgid.so

<IfModule cgid_module>
    Scriptsock cgisock
</IfModule>

なので cgisock ファイルは logディレクトリ内に作成されています。

chroot環境下のときの apache と mod_cgid のパスの扱いに齟齬がある?のかなと推測していますが、ちゃんと追って調べていません。

とりあえずこうやれば動く、ということだけ。