さくらの VPS に CentOS7 を入れて SSH と Firewalld の設定につまづいた話

数年前から契約している、さくらインターネットの仮想専用サーバーの1つに「標準OSインストール」から CentOS x86_64 をいれて SSHD と Firewall と Port の設定をしようと思ったけど、うまく行かなったという話です。

さくらの VPS も何件か契約しておりまして、そのうち1つは CentOS 6.1 で動いていました。

これを久しぶりにアップデートしようとしたところ、Upgrade Tool はリンクが切れており、ミラーリストもURIが変わっていて、いろいろ大変なことに気がつきました。

力づくで解決するよりも新規にOSを入れ直して再設定したほうが早そうだったので /etc 以下のいくつかのファイルをローカルに保存して、コントロールパネルから OS を再インストールすることに決めました。

スタートアップスクリプト [Public] CentOS_yum-update を選択して、インストールは無事に終了しました。

# cat /proc/version
Linux version 3.10.0-957.10.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gccversion 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Mon Mar 18 15:06:45 UTC 2019

VNCコンソールは使い勝手が悪いので、さっそくリモートからのアクセスを許容すべく、ポートの割当を書き換えて SSHD を再起動します。

# vi /etc/ssh/sshd_config
# systemctl restart sshd.service

つぎに割り当てたポートを開放し、不要なポートを閉鎖すべく、Firewalld の設定を書き換えます。

CentOS 6 までの iptables とは勝手が違いますね。

# start systemctl start firewalld
# firewall-cmd --version
0.4.4.5
# firewall-cmd --remove-service=ssh --permanent 
# firewall-cmd --add-service=ssh --zone=public --permanent
# cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/ssh.xml
# vi /etc/firewalld/services/ssh.xml
# firewall-cmd --reload
# firewall-cmd --list-all|grep -a port

リモートから接続されている場合、Firewalld を起動すると一度ここで通信が切断されます。




これで設定がうまく行ったのかと思いきや、ssh 接続を試みると Connection timed out でエラーになります。

何かがおかしいなと思い、開放されているポートを調べてみるのですが、設定的に間違いはなさそうです。

# ss -t -l -n
# grep -i port /etc/ssh/sshd_config

何かがおかしいので、一時的に22番ポートを開放すると、普通に ssh 接続できるようになります。

# vi /etc/ssh/sshd_config
# systemctl restart sshd.service
# vi /etc/firewalld/services/ssh.xml
# firewall-cmd --reload

これは一体どういうことなの???

ほかに理由が思い当たらないので「あまり意味はないだろうな」とも思いつつ、SELinux の設定も変更してみます。

# semanage port --add --type ssh_port_t --proto tcp NNNN
# semanage port --list | grep -w ssh

意味はないだろうとは思っていましたけど、当然ながら結果は同じでした。

調べてみると、さくらインターネットのVPSでは /etc/iptables/iptables.rule に独自の設定を行っているようです。

もしかしたら、22番以外のポートを閉じる設定をどこかで行っているのでないかと、総当りで探していると、こんなものを発見。

2019年6月27日 さくらのVPS 「パケットフィルタ」提供開始のお知らせ 
https://www.sakura.ad.jp/information/announcements/2019/06/27/1968200552/

新機能のパケットフィルタによってOSインストール時にはデフォルトで 22 番以外のポートが閉じられている設定になっていました。

しかも、パケットフィルタが導入されたのは、今日から数えて30日前の 6月27日 です。

これでは新しすぎて、いくら検索しても同一の事例が見つからないわけです。ほかの契約サーバでは問題なく ssh 接続できるのに、このサーバだけ接続できない理由にも合点がいきました。

結局、ネットワークの設定をほとんど見直して、半日を費やしましたけどコントロールパネルからパケットフィルタを無効化すると、問題なくリモート接続できるようになりました。

こうなったら、あとはもう SSH root login と Password Authentication を禁止、御役御免の22番は閉鎖して、ユーザー作成と公開鍵認証を済ませてしまえば、いつもどおりです。

# adduser piyo && usermod -aG sudo piyo
# mkdir /home/piyo
# su piyo && cd ~
$ mkdir /home/piyo/.ssh && chmod 700 /home/piyo/.ssh && sudo chown piyo:piyo /home/piyo/.ssh
$ touch /home/piyo/.ssh/authorized_keys && chmod 600 /home/piyo/.ssh/authorized_keys

いつの間にか、いろいろ変わっているので、定期的に環境を見直しておかないとダメですね。


[改訂新版]プロのためのLinuxシステム構築・運用技術 (Software Design plus)

Knex.js で日付範囲指定の検索したり・バッチ処理で更新や削除したり

最近 (今年の2月ぐらいに) 興味深い記事を読みました。

クエリビルダを利用する明確な利点は存在しないという内容です。ここ3年ぐらいの間に割と聞かれるようになったやつです※。

Stop using Knex.js — Using SQL query builder is an anti-pattern
https://medium.com/@gajus/stop-using-knex-js-and-earn-30-bf410349856c

その趣旨を一言で述べると、動的に作成される必要があるクエリにのみ例外的に Knex.js を使用して、それ以外は直に SQL を書いたほうが良いというもの。

Knex.js というのは node.js において最もよく使われている SQL クエリビルダで、私も手を抜くときに使っています。

MySQL にも PostgreSQL にも SQLite3 にも (不完全ながら DB2 にも) 対応しており、SQL を知っている人にとっては直感的に使えます。

何が良いというわけではないのですけれども、無意識に自然と使用していることが多いです。 SQL を直書きするときでさえ、気がつくと knex.raw() 関数を使っています。

しかし、データベースの一部の機能が使用できない、あるいは使用できないという誤解に基づき酷評されている場面を見たことがあります。

ここからが上の記事の内容なのですが、SQL で実現可能なことをクエリビルダで実現するために二度の学習が必要となり、knex.js に詳しい人も (SQLに詳しい人に比べれば) 少ないので問題が起こった際に調べる手間が大きいことが難点です。

そして、バッチ更新のように利用頻度が高いものが、公式ドキュメントに書かれていない (いま再確認したら batchInsert は書かれていましたけど) ので、それも誤解の一因になっているのかと思いました。

Knex.js – A SQL Query Builder for Javascript / Latest Release: 0.16.3
https://knexjs.org/




ドキュメントに書かれていないので、誤解されても仕方がないですが、データの更新 (UPDATE) や削除 (DELETE) を knex.js でバッチ処理で実行することは可能です。

もとのソースコードの SQL 文の生成あたりを読んでいて、トランザクションの中にクエリ (Array objects) を入れてみたら実行できるような気がしたので、ためしに入れてみたところ… 実際に動作することを確認できました。

できる根拠を尋ねられても、もう当時の考えを覚えてないので困ってしまうのですけれども、やってみたら実行できたのですよ。

const express = require('express');
const router = express.Router();
const knex = require('knex')({
  client: 'sqlite3',
  connection: {
    filename: "./myname.sqlite"
  }
});

/* Connect to (MySQL|PSQL|SQLite) */
router.get('/', (req, res) => {
  let tableName = 'name';
  let query = [{
      id: 1,
      name: 'Janie Doe'
    },
    {
      id: 2,
      name: 'Richard Roe'
    },
    {
      id: 3,
      name: 'John Schmoe'
    }];
  knex.transaction(trx => {
      let built = query.map(elem => {
        return knex(tableName)
          .where('id', elem.id)
          .update(elem)
          .transacting(trx);
      });
      return Promise.all(built)
        .then(trx.commit)
        .catch(trx.rollback);
    })
    .then()
    .catch();
});
module.exports = router;

このソースコードは myname という DB に name というテーブルを作成して、 hoge とか huga とか piyo とか foo とか waldo みたいな適当な初期値を入れておけば実行できます。

削除したい場合には、update(elem) の部分を del() に書き換えると同様に実行できます。もちろん、insert() に書き換えても動きます。

実行環境は以下のとおりです。

$ uname -a
Linux Ganymede 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ node -v
v12.2.0

$ grep -i knex package.json 
    "knex": "^0.16.7",

$ sqlite3 --version
3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d

同じように公式ドキュメントには書かれていないのですけれども、日付の範囲指定なども whereBetween() 関数の中に入りそうに見えたので、入れてしまうとやっぱり動きます。

こうすると簡単かつ柔軟に範囲を指定できるようになって便利なんですよね。

const express = require('express');
const router = express.Router();
const knex = require('knex')({
  client: 'sqlite3',
  connection: {
    filename: "./mylog.sqlite"
  }
});

router.get('/', (req, res) => {
  let tableName = 'access';

  const offset = 8; // UTC time offset HKT 
  //const offset = 9;  
  let currentDate = new Date();
  currentDate.setTime(currentDate.getTime() + 60 * 60 * 1000 * offset);

  let nextDate = new Date();
  nextDate.setTime(nextDate.getTime() + 60 * 60 * 1000 * offset);
  nextDate.setDate(nextDate.getDate() + 1);

  let cd = currentDate.toISOString().split('T')[0];
  let nd = nextDate.toISOString().split('T')[0];

  knex(tableName)
    .select()
    .whereBetween('date', [cd, nd])
    .orderBy('date', 'desc')
    .then(rows => {rows.forEach(elem => {console.log(elem);});})
    .catch();
});
module.exports = router;

このように knex.js には、公式には謳われていなくても、既知の関数の組み合わせで実現できることがたくさんあります。

SQL で実行できることは、何かしらの方法で実行できることが多いです。

できそうに思えたのに実行できなかったのは OrderBy() の中に Array や連想配列を入れて、複数の条件で並び替えを行うことです (Knex.js ver 0.16.7 までの話で、今後は対応されるかもしれません)。

この場合はデータベース内に VIEW を作成しておいて tableName に VIEW の名前を代入してやると思い通りの結果を得ることができます。

SELECTの中で条件分岐したい場合などにも、あらかじめ VIEW を作成しておいて tableName に VIEW の名前を代入してやると簡単です (これもドキュメントに書いてあったかどうか…) 。

でも、それは「SQL で同じことができることを経験的に知っているからではないか」と言われてしまうと、冒頭の話題を考えざるを得なくなるわけです。

SQLで直にクエリを書くことを考えると、どちらが良いのでしょうね。


SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)


※ 一例をあげると

Why you should avoid ORMs (with examples in Node.js)
https://blog.logrocket.com/why-you-should-avoid-orms-with-examples-in-node-js-e0baab73fa5

Breaking Free From the ORM: Why Move On? Time to escape object relational mapping
https://medium.com/building-the-system/dont-be-a-sucker-and-stop-using-orms-190add65add4

出張や旅行で大活躍する Chromebook

私が初めて購入したコンピュータはポリカーボネートの MacBook でした。OS X Tiger という完成度の高い OS と Intel CPU が搭載されており、「性能の割に安くて実用的だ」と私の周囲では評判が良かったのです。

他のマシンに乗り換える必要性も高くなかったので、そこからバックアップデータを引き継ぎながら MacBook を 10 年以上も使い続けてきました。もちろん、ハードウェアの方は何度か新しい機種に更新しています。

専用に設計されたハードウェアと UNIX ベースの安定した OS があって、周辺機器が問題なく使えて、商用ソフトウェアも充実しているので、結局、もっとも使いやすいんですよ。デスクトップ Linux を常用するのはいろいろな意味で大変とわざわざ書いたのは、これが言いたかったからです。

ところが、最近の MacBook はもはや割安で実用的なマシンとは言いづらくなってしまいました。マシンスペックも価格も「高級なハイエンドモデル」と形容した方が適切です。

そして、かつての MacBook に感じていたことを現在は Chromebook に感じています。




利用者に小難しい設定やファイルの存在を意識させないようにうまく隠蔽しているところ、直感的に使えて動作が軽快なところ、また、普通の Windows パソコンで可能なことができないところなどが、そう感じさせるのかもしれません。

当然ながら Chromebook は MacBook ほど万能で高性能ではありません。基本的に動作するのは Web ブラウザ、Android アプリ、Linux の3つだけです。ウィンドウもその3つに加えて、ファイルマージャーと設定ウィンドウぐらいしか立ち上がりません。Gmail アイコンをクリックすると Chrome ブラウザが立ち上がるような OS です。

価格設定も大きく異なり、安いモデルであれば $200 から購入できてしまいます。そして、誰にでも使えて、モバイルノートPCに期待されている機能のほとんど有しています。

すなわち、外出先でのメールの閲覧、スクリーンをプロジェクターに投影しての発表、USBケーブルを用いたデータの転送などです。

出張に出かけた先でプレゼンテーション資料をプロジェクターに写したり、重要な資料やメールをプリンターに出力して印刷したり、デジタルカメラで撮影した画像を USB ケーブルを介して外付け SSD に保存したり、画像加工して SNS に投稿したり、ブログを書いたりすることは問題なく行えます。

Webブラウザでできること 問題なくできます
Gmail以外のEメールの利用 Android アプリをインストールすればできます。Gmailほど便利ではありません。
プロジェクターへの出力 完全に保証まではできませんが、私が使用してきた限りでは問題になったことはありません。
印刷 完全に保証まではできませんが、私が使用してきた限りでは問題になったことはありません。
NAS (SMB/CIFS) の利用 File System for Windows Extensionをインストールすれば使えます。設定時にネットワークの知識が必要です。
PFU ScanSnap の利用 Android アプリをインストール可能ですが、現状では Chromebook 単体での設定が行えません。
Adobe Photoshop の利用 アプリ以外は対応していません
Adobe Illustrator の利用 アプリ以外は対応していません
Wine†/CrossOver の利用 Intel CPU 搭載モデルなら検討の余地あり?
Apple iTunes の利用 できません
NC制御など特殊なソフトウェアの利用 できません

Webブラウザの Chrome と同じ名前が付いていることからも分かるように、とにかく Chrome ブラウザをよく使う OS です。

実際のところ、Chrome ブラウザだけでも表計算やプレゼンテーションなどのオフィススイートの利用や動画の閲覧、果ては画像編集までできてしまいます。

ファイルの存在を意識させない UI や Android アプリを利用できるところなどは、まるでタブレット端末のようですが、PCユーザーの慣れ親しんできた Ctrl + t 、 Ctrl + r 、 Ctrl + spacebar などのショートカットキーも違和感なく利用できます。

むしろキーボードだけなら MacBook Pro のバタフライキーボードよりも使いやすいです。ただし Alt + F4 などは使えません。 そもそもファンクションキーがありません。

それからタブレット端末との大きな違いとして、Linux がそのまま動きます。

大事なことなので2回言いますと、最初から Vim が使えて Perl や Python や apt が動きます。Chromium OS からして Linux distro みたいなものなので動かないわけがありません。

開発者向けのスペックではありませんので、開発を行うことまではしたくありませんが、ローカル環境で動作確認したり、SSHでサーバーに接続したり、正規表現を使ってファイルを一括編集したり、いろいろ自動化したりと、できることの幅が圧倒的に広がります。

よくよく考えてみると、敢えて調べようとしなければ、ハードウェアのスペックすら意識することがないと言うのは凄いですね。それだけ動作も軽快で、不満を感じることは少ないです。

外出先で持ち歩くものだからこそ、データを守るためのクラウドストレージ、故障や盗難を気にせずに使える価格設定、性能よりも省電力を優先した設計は極めて合理的です。

そして最新の機種では USB Type-C 充電器の採用されています。Linux に並ぶ最大の利点であり、Chromebook の実用性をさらに高めています。

USB-C ケーブル1本だけで対応する PC も、スマートフォンも、カメラも、モバイルバッテリーも、 SSD ストレージも使用できます。充電器1つあれば、全ての機器に使いまわすことも可能です。

こんな小さなことが積み重なると総合的な使いやすさに効いてくるんですよ。これが普通のノートPCであれば、直ぐに入れ替えるわけにはいかないかもしれません。

でも $200 の Chromebook であればこそ明日からでも導入が可能です。

ここまで言いましたが、Microsoft Surface Go でも同じような使い方ができます。むしろ拡張性や対応するソフトウェアと周辺機器だけを考えると、こちらのほうが使いやすいかもしれません。大抵の Cromebook では比較にならないほど薄型軽量ですし。

Chromebook の利点となると、どうしても Google Drive や Linux になってしまいますので、それらを使わない人にとっては安価な動画鑑賞パソコンになってしまうのは自然なことかもしれません。


マイクロソフト Surface Go (128GB/8GB) MCZ-00014

しかし、軽量で安価で起動もおそろしく早いモバイルノートPCは、それだけでも出張や旅行には役立ちます。まして全データが自動的にクラウドにバックアップされるモデルなど、探してもなかなか見つかりません。

私の知人もスーツケースを盗まれていますし、私も発砲事件に遭遇したことがありますし、何よりも移動距離が長いと (荷物も増えて持ちきれずに) PCもスーツケースに入れて運ぶようになるので、データが守られているのは心強いです。


ASUS Chromebook Flip C101PA シルバー 10.1型ノートPC OP1 Hexa-core/4GB/eMMC16GB/C101PA-OP1

現状では誰にでも薦められるわけではありませんが、モバイル PC にはマシンパワーを求めない、必ずしも Windows と Microsoft Office を必要とする環境にいるわけではない、用途に応じて PC を使い分けられるなどの割り切りができる人には最高に使いやすいモバイル端末です。

私にとっては長らく待ち望んできた Linux 専用設計の薄型軽量ノートPCでもあります。種類や対応する周辺機器の数が増えるようにもっと普及してほしいです。


† Linux などの UNIX 系 OS 上で Windows 用に開発されたソフトウェアを実行するためのフリーソフトウェアです。完全に互換性があるわけではありません。