子熊のゾルバ@cryptocurrency

仮想通貨の役立つ情報をお届けします。

仮想通貨の取引を全部無料で自動化する! (Gekko + Google Cloud Platform + Freenom + MyDNS + Let's Encrypt) その五 Google Cloud Platformでのサーバー構築の続き

俺の名を言ってみろ!!

f:id:zorbathelittlebear:20170920011918p:plain


子熊のゾルバです。
前回に引き続き、Google Cloud Platformでサーバー構築を行っていきます。

前回の記事はこちら

仮想通貨の取引を全部無料で自動化する! (Gekko + Google Cloud Platform + Freenom + MyDNS + Let's Encrypt) その一 自動取引の概要説明 - 子熊のゾルバ@cryptocurrency

仮想通貨の取引を全部無料で自動化する! (Gekko + Google Cloud Platform + Freenom + MyDNS + Let's Encrypt) その二 Freenomでのドメインの取得 - 子熊のゾルバ@cryptocurrency

仮想通貨の取引を全部無料で自動化する! (Gekko + Google Cloud Platform + Freenom + MyDNS + Let's Encrypt) その三 MyDNSでのダイナミックDNS設定 - 子熊のゾルバ@cryptocurrency

仮想通貨の取引を全部無料で自動化する! (Gekko + Google Cloud Platform + Freenom + MyDNS + Let's Encrypt) その四 Google Cloud Platformでのサーバー構築 - 子熊のゾルバ@cryptocurrency

Google Cloud SDKのインストール

Google Cloud Platformの管理や、VMインスタンスへのSSHアクセスにはGoogle Cloud SDKが必要となります。ここでは、Windowsへのインストール方法について説明します。

こちらのリンクからGoogle Cloud SDKインストーラーをダウンロードします。

Windows 用のクイックスタート  |  Cloud SDK のドキュメント  |  Google Cloud Platform

f:id:zorbathelittlebear:20170926234443p:plain


インストーラーを実行するとインストールウィザードが開始します。Nextをクリックします。

f:id:zorbathelittlebear:20170926234523p:plain


I Agreeをクリックします。

f:id:zorbathelittlebear:20170926234621p:plain


All Usersを選択し、Nextをクリックします。ユーザーアカウント制御のメッセージが表示されるので、はいを選択します。

f:id:zorbathelittlebear:20170926235025p:plain


Nextをクリックします。

f:id:zorbathelittlebear:20170926235309p:plain


Installをクリックします。

f:id:zorbathelittlebear:20170926235335p:plain


緑のバーが右まで到達したらNextをクリックします。

f:id:zorbathelittlebear:20170926235405p:plain


Finishをクリックします。

f:id:zorbathelittlebear:20170927003717p:plain


Google Cloud SDK Shellが起動し、'gcloud init'コマンドが自動的に実行されます。Yを入力しEnterキーを押すと、自動的にブラウザが起動します。

f:id:zorbathelittlebear:20170926235630p:plain


ブラウザでGoogleアカウントへのログインを行います。メールアドレスを入力します。

f:id:zorbathelittlebear:20170926235723p:plain


パスワードを入力します。

f:id:zorbathelittlebear:20170926235844p:plain


許可をクリックします。

f:id:zorbathelittlebear:20170926235917p:plain


以下の画面が表示されたら認証が完了です。ターミナルに戻りましょう。

f:id:zorbathelittlebear:20170927000012p:plain


既に作成済みのプロジェクトに接続するので、1を入力してEnterを押します。

f:id:zorbathelittlebear:20170927000227p:plain


Yを入力してEnterを押します。

f:id:zorbathelittlebear:20170927000436p:plain


デフォルトのゾーンを設定します。VMインスタンスを作成したゾーンの番号を入力し、Enterを押します。(ゾーンを忘れた人は、Google Cloud Platformの管理画面に戻り、Compute Engine > VMインスタンスから、ゾーンを確認します)

f:id:zorbathelittlebear:20170927000650p:plain

f:id:zorbathelittlebear:20170927001336p:plain


特にエラーが無くプロンプトに戻れば、Google Cloud SDKのセットアップは完了です。

f:id:zorbathelittlebear:20170927000835p:plain

Google Cloud SDKからVMインスタンスへのSSH接続

Google Cloud Platformの管理画面から、Compute Engine > VMインスタンスに移動します。プルダウンからgcloudコマンドを表示をクリックします。

f:id:zorbathelittlebear:20170927001449p:plain

*1


コマンドラインをメモします。

f:id:zorbathelittlebear:20170927001714p:plain


Google Cloud SDK Shellに、先程メモしたコマンドを貼り付け、Enterを押します。
例)

gcloud compute --project "moonlit-dynamo-XXXXXX" ssh --zone "us-central1-c" "VMインスタンス名"

f:id:zorbathelittlebear:20170927004936p:plain

*2


初回アクセス時にはSSH認証鍵の生成が行われます、Yをを入力してEnterを押します。

f:id:zorbathelittlebear:20170927005124p:plain


puttyが起動してSSHでのアクセスができるようになります。

f:id:zorbathelittlebear:20170927003055p:plain

*3

もしアクセス出来ない場合、ファイアウォール設定を見直し、現在のIPアドレスがdefault-allow-sshのIP範囲に含まれているか確認します。

パッケージのインストール

インストールされているパッケージを最新にバージョンアップしましょう。

sudo apt-get update && sudo apt-get -y dist-upgrade

必要なパッケージをインストールします。

sudo apt-get -y install git build-essential nginx letsencrypt sqlite nodejs npm apache2-utils fail2ban geoip-bin geoip-database apt-file

kernel等が更新された場合は再起動されないと読み込まれないので、一旦再起動します。

sudo reboot


SSHが切断されるので、OKをクリックします。

f:id:zorbathelittlebear:20170927004235p:plain


自動では再接続してくれないので、Google Cloud SDK Shellからもう一度gcloud computerコマンドを実行します。(カーソルキーの上を押し、Enterを押す)


ログインが終わったら管理者権限(root)で作業します。

sudo su -

プロンプトが"$"から"#"に変わったことを確認します。以下の作業はこの状態でないとうまく行きません。

nginxのセットアップ

では、nginxのサイト設定ディレクトリに移動します。

cd /etc/nginx/sites-available/

初期設定ファイルのバックアップを取っておきます。

mv default default.bak

nginx用の設定ファイルを書き込みます。全部コピー&ペーストして下さい。
server_nameとssl_certificateに設定しているhogehoge.gaというドメイン名は例なので、Freenomで取得したドメイン名に変更します。

cat << '__EOF__' > default
# Deny HTTP access with invalid hostname
server {
    listen 80 default_server;
    server_name _;
    return 444;
}

# Accept HTTP access with valid hostname
server {
    listen 80;
    root /var/www/letsencrypt;
    server_name hogehoge.ga; # Change domain name to yours
    server_tokens off;

    # Accept access to directory used by Let's Encrypt certificate renewal
    location ^~ /.well-known/acme-challenge/ {
        allow all; 
    }

    # Otherwise deny access
    location / {
        return 444;
    }
}

__EOF__

ファイルが正しく書き込めたか確認します。

cat default

Let's Encryptの証明書生成時に使用するディレクトリを作成します。

mkdir /var/www/letsencrypt

Gekkoへのアクセス時に使用するユーザー名、パスワードを指定します。以下のUSERNAME、PASSWORDは好きな文字列でよいですが、ある程度複雑なものを設定します。

htpasswd -bc /etc/nginx/.htpasswd USERNAME PASSWORD

一度nginxの設定が正しいか確認しておきましょう。

nginx -t

設定の書式が合っていれば以下のように表示されます。

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

設定を読み込ませるため、一度nginxを再起動します。

systemctl restart nginx

Let's Encryptからの証明書取得

以下の例では、-dオプションでドメイン名にhogehoge.gaを指定していますが、Freenomで取得したドメインに変更してください。-mオプションで指定しているメールアドレス(xxx@example.com)も、使用しているメールアドレスにします。(Gmail等のアドレスでOKです)

letsencrypt certonly --webroot -w /var/www/letsencrypt -d hogehoge.ga --agree-tos -m xxx@example.com -n

成功すると以下のようにCongraturations!と表示されます。

IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to xxx@example.com.
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/hogehoge.ga/fullchain.pem. Your cert will
   expire on 2017-12-29. To obtain a new version of the certificate in
   the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

成功していたら、nginxの設定ファイルにHTTPS用の設定を追記します。
まず設定ファイルのディレクトリに移動します。

cd /etc/nginx/sites-available/

以下のコマンドをすべてコピー&ペーストし、HTTPS用の設定を追記します。
今回は">>"で追記という意味になっている事に注意して下さい。">"だと上書きとなり、今の設定が消えます。
*4

cat << '__EOF__' >> default
# Gekko configuration as upstream service
upstream websocket {
    server localhost:3000;
}

# HTTPS reverse proxy configuration for Gekko
server {
    listen 443 ssl;
    root /var/www/html;
    server_name hogehoge.ga; # Change domain name to yours
    server_tokens off;

    # Set strong encryption
    ssl_protocols TLSv1.1 TLSv1.2;

    # Set Let's encrypt certificate
    ssl_certificate /etc/letsencrypt/live/hogehoge.ga/fullchain.pem; # Change domain name to yours
    ssl_certificate_key /etc/letsencrypt/live/hogehoge.ga/privkey.pem; # Change domain name to yours

    # Add some security related headers
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;

    # Gekko configuration 
    # https://gekko.wizb.it/docs/installation/installing_gekko_on_a_server.html
    location / {
            proxy_buffers 8 32k;
            proxy_buffer_size 64k;

            proxy_pass http://websocket;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;

            # Authentication needed
            auth_basic "Restricted Content";
            auth_basic_user_file /etc/nginx/.htpasswd;
    }
}
__EOF__

nginxを再起動し、HTTPSの設定と証明書を読み込ませます。

systemctl restart nginx

もし失敗する場合、トラブルシューティングを参考にしてみて下さい。

crontabの設定

MyDNSへのIPアドレス通知と、Let's Encryptの証明書更新をcronで自動的に行うための設定を行います。

crontab -e

最初にcrontabを起動するときに、どのエディターを使うか質問されます。
デフォルトのnanoを使用する場合、そのままEnterキーを押します。

no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.basic
  4. /usr/bin/vim.tiny

Choose 1-4 [2]:

以下のような文字が表示されるので、カーソルキーの下を押し、一番下の行に移動します。

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
<===ココまで移動

以下の文字列をクリップボードにコピーし、ターミナル上で右クリックしてペーストします。
1行目のUSERNAMEとPASSWORDはMyDNSからメールで届いたものを入力します。

*/10 * * * * /usr/bin/curl -v --user USERNAME:PASSWORD https://ipv4.mydns.jp/login.html > /var/log/mydns.log 2>&1
48 20 * * * /usr/bin/letsencrypt renew > /var/log/letsencrypt-renew.log 2>&1 && /bin/systemctl reload nginx > /var/log/systemctl-reload-nginx.log 2>&1 

*5

ペースト後カーソル行の左側が$記号に変化し、貼り付けに失敗したように見えますが、カーソルキーの左を押すとちゃんと表示されるはずです。

*/10 * * * * /usr/bin/curl -v --user USERNAME:PASSWORD http://www.mydns.jp/login.html > /var/log/mydns.log 2>&1
$d-nginx.log 2>&1


Ctrlキー + oで保存します。画面下部に以下のように表示されるので、Enterキーを押して続行します。

File Name to Write: /tmp/crontab.96HcXA/crontab
^G Get Help                 M-D DOS Format              M-A Append                  M-B Backup File
^C Cancel                   M-M Mac Format              M-P Prepend                 ^T To Files

Ctrlキー + xで終了します。プロンプトに戻ります。


cronが正しく設定されたか確認します。貼り付けた文字が表示されていればOKです。

crontab -l

fail2banで不要なアクセスを遮断

nginxでGekkoへのアクセスに認証を設定しています。ここでは、認証が5回失敗したら30分間アクセスを遮断するようにします。

アクセス遮断が発動する条件を設定します。nginxのログに401(認証失敗)が出力された場合に発動するようにします。

cat << '__EOF__' > /etc/fail2ban/filter.d/nginx-401.conf
[Definition]
failregex = ^<HOST> -.* 401
ignoreregex =
__EOF__

アクセス遮断をどのように行うか設定します。
ここでは、maxretry = 5、findtime = 120なので、120秒間の間に5回ログインが失敗したら実行します。
bantime = 1800なので、遮断時間は1800秒(30分)です。

cat << '__EOF__' > /etc/fail2ban/jail.d/nginx-401-jail.conf
[nginx-401]
enabled = true
port    = https
filter  = nginx-401
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 120
bantime = 1800
__EOF__

HTTPに対してのファイアウォールルールは、Let's Encryptからのアクセスを受け入れるため全IPアドレスから許可しています。
Let's Encrypt以外からのしつこいアクセスもついでに禁止してしまいましょう。

HTTPへのアクセスは基本的に444(RSTを応答)がログに残るようにしています

cat << '__EOF__' > /etc/fail2ban/filter.d/nginx-444.conf
[Definition]
failregex = ^<HOST> -.* 444
ignoreregex =
__EOF__

こちらは300秒に2回444が発生したら1週間アクセスを遮断するというルールです。

cat << '__EOF__' > /etc/fail2ban/jail.d/nginx-444-jail.conf
[nginx-444]
enabled = true
port    = http
filter  = nginx-444
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 300
bantime = 604800
__EOF__

fail2banに設定を読み込ませます。

systemctl reload fail2ban

だいぶ長くなってしまいましたので、今回はここまでにしておきましょう。お疲れ様でした!
CLIでの作業で手順も複雑なので、もしわかりづらければお気軽にコメント下さい。
セットアップ作業の8割位は終了しているので、もう少しお付き合いください。。

トラブルシューティング

もし証明書の取得に失敗する場合、以下のような点を確認します。

  1. 名前解決ができるか
  2. nginxが起動しているか
  3. ファイアウォールの設定が正しいか

①名前解決ができるか
"nslookup ドメイン名"というコマンドで、IPアドレスが解決できるか確認します。以下、hogehoge.gaというドメインの例です。

# nslookup hogehoge.ga
Server:		169.254.169.254
Address:	169.254.169.254#53

Non-authoritative answer:
Name:	hogehoge.ga
Address: xxx.xxx.xxx.xxx

xxx.xxx.xxx.xxxの部分が、Google Cloud Platformの外部IPと一致していれば問題ありません。

もし一致していない場合、FreenomでのChange Nameserversの設定が正しく行われているか確認します。
また、MyDNSでのドメイン設定が正しいか確認します。

その後以下のコマンドを実行し、MyDNSに改めてIPアドレスを通知します。USERNAME:PASSWORDには、MyDNSから届いたメールに記載のものを指定します。

curl -v --user USERNAME:PASSWORD http://www.mydns.jp/login.html

以下、実行結果例です。

# curl -v --user USERNAME:PASSWORD http://www.mydns.jp/login.html
*   Trying 210.197.74.203...
* Connected to www.mydns.jp (210.197.74.203) port 80 (#0)
* Server auth using Basic with user 'USERNAME'
> GET /login.html HTTP/1.1
> Host: www.mydns.jp
> Authorization: Basic XXXXXXXXXXXXXXXXX=
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK <=== ココ
< Date: Sun, 01 Oct 2017 11:24:38 GMT
< Server: Apache
< Vary: Accept-Encoding,User-Agent
< Content-Length: 612
< Content-Type: text/html; charset=UTF-8
< 
<html>
<head>
<title>Free Dynamic DNS (DDNS) for Home Server and VPS etc  | MyDNS.JP</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<LINK href="./site.css" rel=stylesheet type=text/css>

</head>
<BODY BGCOLOR="#FFFFFF"
      TEXT="#304040"
      leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"
>
Login and IP address notify OK.<BR>
login_status = 1.<BR>
<BR>
<DT>MASTERID :</DT><DD>mydns776352</DD>
<DT>REMOTE ADDRESS:</DT><DD>xxx.xxx.xxx.xxx</DD> <=== ココ
<DT>ACCESS DAYTIME:</DT><DD>2017/10/01 20:24</DD>
<DT>SERVER ADDRESS:</DT><DD>210.197.74.203</DD>
<BR>

</body>
</html>
* Connection #0 to host www.mydns.jp left intact

チェックするポイントとしては、サーバーから200 OKというレスポンスがあり、REMOTE ADDRESSにGoogle Cloud Platformの外部IPが表示されている事です。もう一度"nslookup ドメイン名"を入力すれば、IPアドレスが表示されるはずです。

②nginxが起動しているか
"systemctl status nginx"コマンドでnginxが起動している(active (running))という表示になっている事を確認します。

# systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-09-30 13:05:16 UTC; 21h ago


ファイアウォールの設定が正しいか
ファイアウォールルールを確認し、default-allow-httpのIP範囲が0.0.0.0/0となっている事を確認します。

参考サイト

Installing Gekko - Gekko

Installing Gekko on a server - Gekko


____________________

以下、アフィリエイトです。もしこの記事がお役に立ちましたら、こちらから取引所口座を開設頂けると励みになります。(私のお小遣いになります)

日本では以下の3つが主要な仮想通貨取引所となります。

 

インチェック

初心者でも簡単に仮想通貨が購入できます。また、ビットコイン以外の仮想通貨(オルトコイン)も12種取り扱っているのも高ポイントです。ただし、購入手数料が高いのが難点。  

ビットコイン取引高日本一の仮想通貨取引所 coincheck bitcoin
 

bitFlyer

日本で最もビットコインの取引量が多い(=売買が成立しやすい)取引所です。多額の取引をする場合におすすめ。 無難ですが、特に突出した特徴が無いのが難点と言えば難点。

bitFlyer ビットコインを始めるなら安心・安全な取引所で


Zaif

私がメインで使っている取引所。手数料がマイナスなので、取引すればするほど得をします。 XEMを購入するならここ。サーバーが貧弱なのかたまに応答しなくなるのが難点。 

*1:ファイアウォールルールで許可する接続元IPアドレスを自宅のみに設定しているはずなので、ブラウザウィンドウで開くのオプションは使用できません。

*2:gcloud initでデフォルトのプロジェクトやゾーンの設定が完了しているので、「gcloud compute ssh "VMインスタンス名"」だけでもアクセスができます。

*3:Linuxへのログインユーザーが接続方法により異なります。ブラウザからのSSHアクセスの場合にはGoogleアカウント(@より前の部分)、WindowsGoogle Cloud SDKの場合Windowsでログイン中のユーザー名となります。

*4:最初にHTTPSの設定を入れなかったのは、まだHTTPS用の証明書がなく、nginxを起動しようとしてもエラーで起動しなくなるためです。

*5:上の行は、10分毎にMyDNSにIPアドレスの通知を行う設定です。下の行は、毎日20時48分(UTC)に証明書が必要か確認し、必要であれば更新を行います。それぞれ最後の実行結果は/var/log/ディレクトリの下にログを保存するようにしています。