それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

github でLFSを使う

github 遅い。。。

github は基本的に遅いので、ちょっとしたバイナリでも追加すると重くなる。

git だけで使ってる分には気にならないんですが、github と連携してpush にバイナリが混じり始めると遅い。

そこでGitHubでもLFSを使うことに。

githubLFSでデータを送る

github にはLFSでデータを送付することが出来ます。

ローカル git レポジトリでLFSを使う

git lfs track '*.pdf'

ファイルを追加する

git add ./*.pdf

LFSで追加されたことを確認

git lfs ls-files

コミットしてpush

コミット

git commit -m 'initial import to LFS'

プッシュする

git push 

転送速度はLFSのほうが早い??

LFS使ったほうがGithubの転送速度は早いような気がした。

PDFを入れるなよって思われるかもしれないですけど。ちょっと用事がありまして。

takuya@gitbook$ git push
Uploading LFS objects: 100% (86/86), 562 MB | 5.5 MB/s, done
Enumerating objects: 100, done.
Counting objects: 100% (100/100), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (98/98), done.
Writing objects: 100% (99/99), 13.44 KiB | 1.92 MiB/s, done.
Total 99 (delta 1), reused 0 (delta 0)

回線速度によりますけど、LFSは5.5MB/s で、通常のGitのテキストファイルは 2.0MiB/sでした。

LFS使うほうがメリット大きいな。 空いてる方を使うべきだ。ってことかなやっぱ。

LFSを使うときの注意点

Gitのレポジトリのpush先を変えたときに、LFSのログが引き継がれないので注意が必要。

そのうち対応してほしいよね。

関連記事

参考資料

日本語(ローマ字)表記をひらがなにする。

日本語(ローマ字)表記をひらがなにしたい

「shatiku → しゃちく」 にしたい

本日の目的 ローマ字で表現された名前を変換したい。

hatarakusaibou のような名前を ’はたらくさいぼう’のようにひらがな表記に変えたい。

ローマ字を'ひらがな'に変換できれば、ひらがなから漢字にできるかもしれない。

ローマ字→ひらがな→漢字 に変換できればいいよね。

力技もある。

tr 使えばできそうよね。正規表現でパターン網羅すれば良いわけですし。

力技で、 'kakikukeko' を 'かきくけこ' に tr すればいいと思ったけども 変換テーブル用意するのも、めんどくさい

調べたら。 romkan という gem があった

使ってみる

bundle add romkan
require 'romkan'
puts "kitakyuushuu".to_kana

実行結果

$ bundle exec ruby sample.rb 
きたきゅうしゅう

お、行けそう。

使うときの注意点

意外と使い所が難しい。

  • waha にする
  • アルファベットの大文字が混じるとおかしくなるので、事前に小文字化しておくと良い
  • 英単語と混じってる場合、スペースなどの区切りで置換対象から除外する。
  • 子音が連続する単語は置換から除外する。

大文字が行頭に混じると困る。例

>> 'Osaka Namba'.to_hepburn.to_kana
=> "Oさか Nあmば"

小文字にするとまだまし

>> 'Osaka Namba'.downcase.to_hepburn.to_kana
=> "おさか なmば"

それでも 難波を Namba と表記されると辛いし、大阪をOsakaと表記されると辛い。

英単語混じりはつらい

たとえば、 Death March からはじまる異世界をローマ字とすると、次のようになる。

>> text = 'Death_March_kara_Hajimaru_Isekai_Kyousoukyoku'
>> puts text.downcase.gsub(/_/,' ').gsub(/ wa /, 'ha').gsub(/\s|_/,'').to_hepburn.to_kana
=> "であthまrchからはじまるいせかいきょうそうきょく"

連続する単語を置換するには厳しそうだ。

子音(小文字)が連続する単語や、末尾が子音で終わる単語を置換対象から外すというヒューリスティックな解決策しかなさそう。

text = 'Death_March_kara_Hajimaru_Isekai_Kyousoukyoku'
puts text = text.downcase.gsub(/_/,' ')
                .gsub(/ wa /, 'ha')
                .split(/\s+/)
                .map{|e| e=e.to_hepburn.to_kana unless  e=~/[^aiueon]$/ ; e   }
                .join(' ')
# => death march から はじまる いせかい きょうそうきょく

こんな感じ??

母音の連続は扱えない

連続する母音は、省略表記されることが多いのだけど、これをうまく扱う方法が思いつかない。

'osaka'.to_kana
#=> "おさか"
>> 'kyushu'.to_kana
=> "きゅしゅ"

なんに使うの?

日本語のローマ字で書かれた、大量のPDFがあったり、HTMLファイルがあったり、テーブル定義があったりします。 読みにくくて仕方がないので、ひらがな・漢字に変換できれば便利になるよね。

参考資料

ruby - mecab をインストールするときにエラーが出たのでメモ

mecab - ruby を使いたい

久しぶりにmecab をインストールしようとしたら・・・

bundle add mecab 

エラーになるんですね。

extconf.rb:12:in ``': No such file or directory - mecab-config

mecab は extconf で外部ライブラリ(.h)を参照するので、 mecabのインストールが必要でした。

エラーの原因:mecab が未インストールでした。

わたしは、macOS なので brew install します。

takuya@$ brew info mecab
mecab: stable 0.996 (bottled)
Yet another part-of-speech and morphological analyzer
https://taku910.github.io/mecab/
Conflicts with:
  mecab-ko (because both install mecab binaries)
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/mecab.rb

ああ、not installed だ。ずいぶん長い間使ってなかったんですね。つまりMacにしてから数年間一度もmacで使ってないわけだ。

mecab 本体のインストール

brew install mecab
brew install mecab-ipadic

これでインストールは完了

ruby mecab のインストール

bundle add mecab

無事終了しました。

Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Using bundler 1.16.2
Fetching mecab 0.996
Installing mecab 0.996 with native extensions
Using romkan 0.4.0
Bundle complete! 2 Gemfile dependencies, 3 gems now installed.
Bundled gems are installed into `./vendor/bundle`

起動テストをします。

動かしてみます。

require 'mecab'
m = MeCab::Tagger.create("-Ochasen")
puts m.parse ("shachou")
bundle exec ruby sample.rb 
shachou shachou shachou 名詞-固有名詞-組織              
EOS

オッケ。

gem install でシステムに依存しない extconf にしてくれたら嬉しいんだけどなぁ。

Wordpressでユーザーテーブル共有

めんどくさい

実験用にWordpressを作るけど毎回毎回、ユーザー作成がめんどくさい。

そうだ、ユーザーテーブルは使いまわしてしまおう。

wp-config だけで解決する

1つ目のWordpress

$table_prefix  = 'blog1_';
define('CUSTOM_USER_TABLE','XXX_wp_users');
define('CUSTOM_USER_META_TABLE','XXX_wp_users');

2つめのWordpress

define('CUSTOM_USER_TABLE','XXX_wp_users');
define('CUSTOM_USER_META_TABLE','XXX_wp_users');
$table_prefix  = 'blog2_';

2つのWordpressでテーブル共有

DB設定はもちろん共有。ユーザ関連だけ共通にする。

権限はブログ事になるので、設定が必要

インストール後にやること

初期設定終わったら、管理権限を与える。 管理者権限はブログ毎に管理されるので、ブログ毎に管理者権限を与えればいい。

既存のWordpressのユーザーを統合するときに問題点

既存のWordpressを統合するなら、投稿者データの紐づけに注意しながらテーブルを混ぜてしまえばいい。ただ、ユーザーテーブルは意外とシンプルで primary key ( auto increment ) かぶりにだけ注意したら簡単に既存のテーブルを統合できた。

新規で作るなら管理者権限を付与すればいんだよね。

実際にやってみたけどめっちゃ簡単なのでおすすめ。

ちゃんとマニュアルに書いてあるんですよね

そうおもうと、Wordpress関連のエントリの情報密度の薄いことと言ったら。。。

参考資料

https://codex.wordpress.org/Editing_wp-config.php

sudo で シェルのaliasされたコマンドを使えるようにするけど、環境変数を渡さない。

sudo するとコマンドnot found

あああ、、もう。

takuya@sakura:~$ sudo ll
sudo: ll: command not found

alias に頼り切ってると、こういうことが頻繁に起きる

解決策

alias sudo='sudo '

コレが解決策

間違った解決策: preserve Environment

sudo -E 

環境変数を渡してしまうと、意図通りの動作をしない可能性があったり、ミスを誘発するから絶対ダメ。(間違いとは言いすぎかもしれないが、過剰な環境変数の引き継ぎは意図しない動作を引き起こしてしまう)

このオプションは、現在の環境変数をすべて sudo 実行時に引き継ぐのでトラブルのもとになると思いう。

alias でうまくいく理由。

たぶんだけど、alias の展開が再帰的に行われるから 。

alias を使って再帰的な展開をつかってbashに解釈させるってことですね。

sudo のかわりに _sudo として考えてみる。

alias ll='ls -l'
alias _sudo='sudo '
_sudo ll

こう書いたとき、alias が展開されるとき、_sudo ll は sudo ls -l として順番にalias を展開済みにしてから プロセスが起動される。

# alias が  alias を展開して
$  _sudo ll 
   →  sudo ll  # ここで更に展開
      →  sudo ls -l
$ sudo ls -l # コレが実行される。

再帰的なalias展開を使うという、シンプルで盲点な解決策があるってことに気づかなかった私を殴りたい。

参考資料

https://wiki.archlinux.jp/index.php/Sudo#.E3.82.A8.E3.82.A4.E3.83.AA.E3.82.A2.E3.82.B9.E3.82.92.E6.B8.A1.E3.81.99

追記 2018/10/28

はてなブックマーク - tarumeのブックマーク / 2018年10月17日

よくわからない説明されてるけど、公式読むと→ http://www.gnu.org/software/bash/manual/bashref.html#Aliases >If the last character of the alias value is a blank, then the next command word following the alias is also checked for alias expansion.

再帰的に展開するっていう説明じゃよくわからないですか。すいません。書き方一部変更します。

1分で作れる誰でも作れるジョークウェア(ウイルス?)で書類送検される時代

メモ帳で出来るもので逮捕・送検される。

1分できるイタズラウイルスの作り方。

Windowsでは、次のようにかけます

  • Windows - R を同時に押します
  • notepad と書いてEnterを押します。
  • start cmd と書いて改行します。
  • Ctrl-A を押したあとに Ctrl-C を押します。
  • Ctrl-V を200回押します。
  • Ctrl-S を押します。
  • ファイル名を 知的好奇心を満たすため.bat と書いて保存します。

あとは、このファイルをダブルクリックして実行すればいい。

start cmd
start cmd
start cmd
start cmd
...(以下数万回位

割と怖い。

たったこれだけで逮捕され、書類送検され、「不正指令電磁的記録の保持」になるとか、ちょっとやばい気がします。

これはウイルスと言えるのだろうか。

実際の逮捕例。

動画投稿サイトを参考に作成したコンピューターウイルスを保管・提供したなどとして、神奈川県警サイバー犯罪対策課と港北署が、不正指令電磁的記録保管などの非行内容で、大阪、東京、山梨各都府県に住む9~11歳の男子児童3人を児童相談所に通告したことが14日、分かった。新潟県に住む県立高校2年の男子生徒(17)も同日、同容疑で書類送検した。  同課によると、児童3人を児相に通告したのは2017年12月。通告内容は、大阪府の小学3年の児童(9)は同5~6月、投稿動画を参考に作成したウイルスを保管し、ネットワーク上のサーバーに転送・掲載した、としている。都内の同4年の児童(9)と山梨県の同5年の児童(11)はそのウイルスをダウンロードした、としている。

 ウイルスを作成するなどした大阪府の児童は「悪いことだと知っていた。これまでに10人以上がダウンロードした」と話し、ダウンロードした2人も「友達を驚かせようと思った」「いたずらに使えると思った」などと動機を語っているという。

 男子生徒の書類送検容疑は同9月、投稿動画を参考に作成したウイルスをサーバー上に保管した、としている。ウイルスの作成方法を自身のブログに掲載していたといい、「閲覧数を増やして広告収入を得たかった」などと供述している。

 いずれのウイルスも、感染するとパソコン画面にウインドーが次々表示され、機能が著しく低下する。県警のサイバーパトロールで発覚した。

https://headlines.yahoo.co.jp/hl?a=20180315-00024554-kana-l14

関連記事

「強制終了して下さい」の無限ループで逮捕されるか。実験してみた - それマグで!

ウイルスの作成方法書いたら逮捕されるらしいので、この記事で私が逮捕されるか社会的な実験です。

GitHubでフォーク元の更新分のマージで最新版にする。

github は手軽にフォーク出来て便利

github で フォーク(fork)後に、フォーク元の更新の差分を、自分のフォークに取り込むための手順とやり方です。

 準備: フォークしたローカル環境(自分のレポジトリ)に移動

cd my-forked-repos

作業:フォーク元の登録

git remote add でfork 元を登録する ローカルのgit にリモートとして、フォーク元を登録します。

git add remote upstream https://github.com/元のレポジトリ.git
  • upstream の名前は、は覚えやすい名前であれば何でもいいです。一般的にupstreamが使われるようです。
  • URL は git@github.com のSSHでもHTTPSでもどちらでもいいです。取得できればオッケ。

フォーク元の更新を取得します。

git fetch upstream 

これで、upstream と名付けたレポジトリの最新コミットを、これを取ってきます。

ローカルのmasterとマージします。

自分のレポジトリのmasterと フォーク元(upsteam)の masrerをマージします。

git checkout master
git merge upstream/master

コンフリクト解決しながら必要であればコミットする

おわったら

## github に送る
git push 

コレで完了。

git の基本機能remote add を使った対応。

github の公式に紹介されてる方法は git remote add を使ったものです。

githubのフォークといえども、gitの基本機能である複数リモートを使って対応するようです。

github 側でfork したときでも、.git/config を自動生成するわけにはいかないので gitのコマンドで対応するのが限界ですね。

git のコマンドで2つ目、3つ目の同期先を指定する。

git remote add origin  $path

参考資料

GitLabでgit lfsを有効にする。

gitlabで lfs を有効にする。

git lfs でPSDとかPNGとか比較的大きなファイルを扱う。

LFSを使えるとデザインデータとかバイナリなどのgit管理が楽になる。っていうか、バイナリはコレを使わないと非効率すぎる。

155 ### Git LFS
156 #  2018-01-01 modifled to enabled by takuya 
157 gitlab_rails['lfs_enabled'] = true
158 gitlab_rails['lfs_storage_path'] = "/var/opt/gitlab-lfs"

設定を変えたら、再起動(omibus版)

sudo gitlab-ctl reconfigure

デフォルト設定

gitlabのデフォルトの設定はつぎのようになってた。

## Git LFS defaults
 gitlab_rails['lfs_enabled'] = false
 gitlab_rails['lfs_storage_path'] = "/mnt/storage/lfs-objects"

注意点

LFSはファイルの格納と差分の扱いを分割するものでありんす。

LFSを使っていると、git clone は早くなるが、リモートレポジトリの移動に難点が出てくるので、注意が必要

サーバー側は単にLFSとしてバイナリを入れてるDropBox的なものに徹しているので、リモートを移動とか移行とかするときは LFSを併せて移動する必要があるのでそこだけ留意しておかないとgit clone して remote add して push しただけだと動かなくなる可能性もある。

2018-11-15 追記

GitLab側で新規レポジトリ作成時にGithubからcloneをWebUIで行ったら、Github LFS → GitLab LFSの移行は、問題なく行えた。結構行けるかも

参考資料

https://docs.gitlab.com/ee/workflow/lfs/lfs_administration.html

sierra以降で野良アプリ(不明・匿名)のアプリケーションを実行する sudo spctl --master-disable

すべてのアプリケーションを許可する設定を復活させる

AppStore と確認済みの開発元からのアプリケーションの許可しか選べない問題。

mac で 起動できないアプリケーション(野良ビルド)を動かす。

すべてのアプリケーションを許可が出てくる。これで問題なく動かせる。 勿論、これは未署名のアプリケーションを動作させる設定なので、本当に慎重にやらなくちゃいけない。 慎重にやらない人がいたら、デフォルトオフにされて設定を消されてしまったわけですしね。

無条件に野良アプリを使えるようにする。

未確認のアプリケーション(証明書が切れてるなど)のMacのアプリを実行できるようにする。

sudo spctl --master-enable

初期状態に戻すには

sudo spctl --master-disable

もしかしたら、csrutil enable --without debug が必要かもしれない。

設定前

f:id:takuya_1st:20180905170155p:plain

設定後

f:id:takuya_1st:20180905170150p:plain

vimdiff を neovimでやるには

vim がなくて vimdiffが使えない。

vim があれば、ファイルの差分をvimdiffで表示できるよね。 git とかJSONを触ってるととっても便利。

vimdiff old new 

でも 最近 neovim なので vimが入ってない、すると vimdiffが使えない。

同じことを neovim でやるには

nvim -d old new

neovim みたいに、vimdiff コマンド単品は用意されてないようですね。

なので、常用するには

alias vimdiff='nvim -d '

こうですかね。

参考資料

https://gist.github.com/huytd/78c676a797f81eb08cdedf5400e1b6a3

mdlsコマンドで アプリケーションのCFBundleIdentifier ( bundle Identifier )の文字列を探す

BundleIdentifier の Identifier ( 識別子文字列)を取り出す。

mac のアプリケーションの識別子こと kMDItemCFBundleIdentifier を調べる。

plutil でxmlgrep して CFBundleIdentifier を調べててたけど。もっと簡単に identifier を調べて、UTI文字列を取り出す方法を見つけたので、メモっておく。

takuya@.bin$ mdls -name kMDItemCFBundleIdentifier  /Applications/Microsoft\ Remote\ Desktop.app
kMDItemCFBundleIdentifier = "com.microsoft.rdc.mac"

mdls コマンドで Appの情報を取り出す

mdls /Applications/Google\ Chrome.app

アプリケーションのPATHを引数に与えてあげればいい。

mdls 自体は、 list の ls と meta data の md の意味らしい。 ( man mdls )

その他の使い方としては、mdlsを使えばファイルのメタデータを取得できるらしい。そのうち調べたい。

takuya@.bin$ mdls
(null): no filename specified!

usage: mdls [-name attr] [-raw [-nullMarker markerString]] [-plist file] path
list the values of one or all the attributes of the specified file
  -raw:         don't print attribute names before values
  -nullMarker:  substitute this string for null attributes in raw mode
  -plist:       output attributes in XML format to file. Use - to write to stdout
                option -plist is incompatible with options -raw, -nullMarker, and -name
example:  mdls  ~/Pictures/Birthday.jpg
example:  mdls  -name Keyword ~/Pictures/Birthday.jpg

コマンドの場所

コマンドは macOSにバンドルされていて、 /usr/bin/ に存在した。

takuya@.bin$ which mdls
/usr/bin/mdls

mdls の取得例

takuya@.bin$ mdls /Applications/Microsoft\ Remote\ Desktop.app
_kMDItemDisplayNameWithExtensions  = "Microsoft Remote Desktop.app"
_kTimeMachineNewestSnapshot        = 4001-01-01 00:00:00 +0000
_kTimeMachineOldestSnapshot        = 2018-08-12 03:51:06 +0000
kMDItemAlternateNames              = (
    "Microsoft Remote Desktop.app"
)
kMDItemAppStoreCategory            = "ビジネス"
kMDItemAppStoreCategoryType        = "public.app-category.business"
kMDItemAppStoreIsAppleSigned       = 1
kMDItemCFBundleIdentifier          = "com.microsoft.rdc.mac"
kMDItemContentCreationDate         = 2017-01-12 00:21:41 +0000
kMDItemContentCreationDate_Ranking = 2017-01-12 00:00:00 +0000
kMDItemContentModificationDate     = 2017-01-18 07:54:08 +0000
kMDItemContentType                 = "com.apple.application-bundle"
kMDItemContentTypeTree             = (
    "com.apple.application-bundle",
    "com.apple.localizable-name-bundle",
    "com.apple.application-bundle",
    "public.directory",
    "public.executable",
    "com.apple.application",
    "public.item",
    "com.apple.package",
    "com.apple.bundle"
)
kMDItemDateAdded                   = 2018-08-13 06:13:02 +0000
kMDItemDateAdded_Ranking           = 2018-08-13 00:00:00 +0000
kMDItemDisplayName                 = "Microsoft Remote Desktop.app"
kMDItemExecutableArchitectures     = (
    "x86_64"
)
kMDItemFSContentChangeDate         = 2017-01-18 07:54:08 +0000
kMDItemFSCreationDate              = 2017-01-12 00:21:41 +0000
kMDItemFSCreatorCode               = ""
kMDItemFSFinderFlags               = 0
kMDItemFSHasCustomIcon             = (null)
kMDItemFSInvisible                 = 0
kMDItemFSIsExtensionHidden         = 1
kMDItemFSIsStationery              = (null)
kMDItemFSLabel                     = 0
kMDItemFSName                      = "Microsoft Remote Desktop.app"
kMDItemFSNodeCount                 = 1
kMDItemFSOwnerGroupID              = 0
kMDItemFSOwnerUserID               = 0
kMDItemFSSize                      = 39006120
kMDItemFSTypeCode                  = ""
kMDItemInterestingDate_Ranking     = 2018-08-31 00:00:00 +0000
kMDItemKind                        = "アプリケーション"
kMDItemLanguages                   = (
    empty
)
kMDItemLastUsedDate                = 2018-08-31 03:58:51 +0000
kMDItemLastUsedDate_Ranking        = 2018-08-31 00:00:00 +0000
kMDItemLogicalSize                 = 39006120
kMDItemPhysicalSize                = 15273984
kMDItemUseCount                    = 4
kMDItemUsedDates                   = (
    "2018-08-21 15:00:00 +0000",
    "2018-08-30 15:00:00 +0000"
)
kMDItemVersion                     = "8.0.27246"

以前の記事

http://takuya-1st.hatenablog.jp/entry/2017/04/23/002406

Macがスリープ時に自動ログアウトするのを防ぐ

かなり重要な設定なのでメモ

High Sierraにすると起動中のプログラムが勝手に終了してしまう。

macOSでは、すべてのプログラムを終了されてしまう。

macOS High Sierraにしてから、離席しているとすべてのプログラムを終了されてしまう。 何言ってるわからないだろ。うん。私も最初何が起きているのか理解できなかったんですね。

最初は、touchID の問題かと思ってだいぶ調べたけれど違いました。

離席して戻ると

「iTermによって終了出来ませんでした、このまま終了するにはiTermを終了して下さい」

このように、アプリの所為で終了出来ないと言われるんですね。これが原因が分からず悩んでた。

iTermや、IntelliJ や、EvernoteChromeでも起きると。なぜ起動中のアプリケーションやプログラムが勝手に終了されてしまうんだろうか。

デフォルトでスリープ時にログアウトする設定

High Sierraではスリープ時にログアウトするんですね。スリープしたらログアウトしてプログラムを終了に掛かるんですね。そしてそう言うことを想定してないプログラムが、未保存のデータがあるので、終了確認を出して来る。Appleさん的には、ログアウトしてもアプリケーションの状態を復元する仕組みがああり、それを使えって言ってるから当然の行為であるという感じなのでしょうが。個人的には非常にめんどくさい。スリープしてて欲しいのに、ログアウトされるのは堪らない。

スリープ時に自動ログアウトする設定をオフにする。

スリープに自動ログアウトする設定をオフにする。この設定も場所が分かりにくくなってる。

以前のキャプチャーがネットに転がっていて、設定項目が喪失しているようにみえるのですが、「詳細」(Advance)に存在する。*1

f:id:takuya_1st:20180901182911p:plain

ここで設定する。

ここで自動ログアウトをオフにすると、スリープしているとき復帰後に「〇〇で終了できませんでした」というメッセージに驚かされる心配がなくなる。

f:id:takuya_1st:20180901182920p:plain

touchID を便利に使うには、必須の設定。

タッチを採用したMacbookだとスリープの復帰にはTouchIDを使えるが、自動でログアウトされると割とめんどくさい、スクリーンロックだと有効にはたらくのに、ログアウトされてしまうとユーザ名をサイド入力する必要が出てくるのでタッチIDがまるで役に立たなくなってしまう。

どうして、この自動ログアウト設定をデフォルトON設定したのか、首を傾げるばかりでした。

参考資料

https://support.apple.com/ja-jp/guide/mac-help/mchlp2443/mac

https://www.macobserver.com/tips/mgg-answers/macos-sierra-disable-auto-logout/

*1:Advanceを詳細と邦訳するのもセンスがないが

ipset と iptables で 楽チンなFW管理

ipset で IPアドレス(またはネットワークアドレス)からの接続を許可する

linux のFWを使うのにアドレス条件を指定すると記述量が半端なく長くなる。

これを解消するために、ipset というコマンドがあり、IPアドレスやネットワークアドレスをグループ化して管理するコマンドがある。これについては以前も記述した。以前の記述が不明確でわかりづらいので書き直す事にした。→ 以前の記事

今回は、ローカルネットワークやローカルネットワーク内の指定ホストからの接続を許可する例を書きます。

それをipsetで書いて、ipsetの使い方を見てゆこうと思います。

iptablesとipsetでポートへのアクセスをIPアドレス(ネットワーク)単位で制御する。

ipset と iptablesを組み合わせて使うと理解しやすくメンテしやすいFWの記述ができる。

準備:インストール

実験に使っているのは、いつもRaspbianなので、apt をつかいます。

sudo apt install ipset

ipset でリストをつくります。

ipset ではネットワークアドレスやIPアドレスを、グループ化して管理するため「リスト」と呼ばれるものを作ります。

今回は、ローカルアドレスを表すリスト(my_hosts)と、ローカルネットワークを表すリスト(my_local )の2つを作ることにします。

リストの作成:ローカルアドレス

リストを作成します。hash:ip はこのリストが、IPアドレスの列挙であると明示しています

# ipset create my_hosts hash:ip

リストの削除

リストを削除するには次のようにします。

# ipset destroy my_hosts

リストに、IPアドレスを追加します。

追加するIPアドレスはローカルのLAN内にいるIPアドレスのつもりです。

# ipset add my_hosts 192.168.11.1
# ipset add my_hosts 192.168.1.1
# ipset add my_hosts 192.168.255.1

追加した結果を確認します

# ipset list my_hosts
Name: my_hosts
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 124
References: 0
Members:
192.168.1.1

リストから項目の削除

項目を指定して削除するには次のようにします。間違ったときや不要になった時に使うと良いでしょう。

# ipset del my_hosts 192.168.11.1
# ipset del my_hosts 192.168.1.1
# ipset del my_hosts 192.168.255.1

ネットワークアドレスのリストを作成

IPアドレスだけでなく、ネットワークアドレスでの範囲指定を単位としたリストを作ることが出来ます。

今度は hash:net をつかいます。先ほどは hash:ip だった。

# ipset create my_local hash:net

ネットワークアドレスのリストへの項目の登録と削除と確認。

これも先ほとど同じです。

# ipset add my_local 192.168.11.0/24
# ipset dell my_local 192.168.11.0/24
# ipset list my_local

再起動後にも設定が維持されるようにする。

ipset が再起動後にもまたロードされる様に、設定を保存する。また、再起動後にロードさせる設定をsystemd に連携させる。

設定の保存

sudo ipset save -f /etc/ipset.conf

設定のロード(リストア)

sudo ipset restore -f /etc/ipset.conf

再起動後にロードさせる systemd 設定をつくる

/etc/systemd/system/ipset.service

[Unit]
Description=ipset restore 
Before=networking.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ipset restore -exist -f  /etc/ipset.conf

[Install]
WantedBy=network.target

どのサービスに入れるかは判断の分かれるところなので、明確な解答はないですね。 iptables やnetworn.serviceのサービス定義の ExecStartPreでも良いと思います。

また、ipset は iptablesと共に使われるので、iptablesの起動設定に含めたり、/etc/network/if-pre-up.d/に記述するのいいともおいます。

iptablesの記述にipsetを使う。

ipsetを保存とリロードが出来たら、iptablesの設定に追加していきます。

my_local からの ssh(tcp/22) 接続を許可する霊

-I INPUT -m state --state NEW -p tcp --dport 22 -m set --match-set my_local src -j ACCEPT

my_hostsからの全ての接続を許可する

-I INPUT  -m set --match-set my_hosts src -j ACCEPT

書き方のポイント

 -m set --match-set my_local src -j ACCEPT
  • -m set Ipset モジュールを指定
  • --match-set セットにマッチする条件を指定
    • my_local ipset で指定したリストを指定
    • src ここではSRCにリストを適用すると条件を指定( src / dst / src,dst のいずれか)

設定はこんな感じでかけた。

iptablesを書いたら保存とリロード

iptablesの保存とリロードは別の記事や他の人がいっぱい書いてるのでそれを参考にする。

man について

詳しい使い方はiptables-extensions(8)の中にあるので、次のマニュアルでsetの章に書いてある。

man 8  iptables-extensions

ipset については次のように書いてあった

   set
       このモジュールは ipsec(8) で定義できる IP 集合にマッチする。

       [!] --match-set setname flag[,flag]...
              where flags are the comma separated list of src and/or dst specifications and there can be no more than
              six of them. Hence the command

               iptables -A FORWARD -m set --match-set test src,dst

              will  match  packets,  for which (if the set type is ipportmap) the source address and destination port
              pair can be found in the specified set. If the set type of the specified set is single  dimension  (for
              example  ipmap),  then  the command will match packets for which the source address can be found in the
              specified set.

       --return-nomatch
              If the --return-nomatch option is specified and the set  type  supports  the  nomatch  flag,  then  the
              matching  is  reversed: a match with an element flagged with nomatch returns true, while a match with a
              plain element returns false.

       ! --update-counters
              If the --update-counters flag is negated, then the packet and byte counters of the matching element  in
              the set won't be updated. Default the packet and byte counters are updated.

       ! --update-subcounters
              If  the --update-subcounters flag is negated, then the packet and byte counters of the matching element
              in the member set of a list type of set won't be updated. Default the  packet  and  byte  counters  are
              updated.

       [!] --packets-eq value
              If the packet is matched an element in the set, match only if the packet counter of the element matches
              the given value too.

       --packets-lt value
              If the packet is matched an element in the set, match only if the packet counter of the element is less
              than the given value as well.

       --packets-gt value
              If  the  packet  is  matched  an element in the set, match only if the packet counter of the element is
              greater than the given value as well.

       [!] -bytes-eq value
              If the packet is matched an element in the set, match only if the byte counter of the  element  matches
              the given value too.

       --bytes-lt value
              If  the  packet is matched an element in the set, match only if the byte counter of the element is less
              than the given value as well.

       --bytes-gt value
              If the packet is matched an element in the set, match only if  the  byte  counter  of  the  element  is
              greater than the given value as well.

       The  packet  and  byte counters related options and flags are ignored when the set was defined without counter
       support.

       The option --match-set can be replaced by --set if that does not clash with an option of other extensions.

       Use of -m set requires that ipset kernel support is provided, which, for standard kernels, is the  case  since
       Linux 2.6.39.

hash:net hash:ip 以外に何があるの?

ipset help 

パッと見た感じ、 net :ネットワークアドレス(範囲)や port ( ポート)や mac アドレスなども含められるようですね。

Supported set types:
    hash:mac        0   Initial revision
    hash:ip,mac     0   Initial revision
    hash:net,iface  6   skbinfo support
    hash:net,iface  0   Initial revision
    hash:net,port   7   skbinfo support
    hash:net,port,net   2   skbinfo support

iptableを書くとしんどい

iptablesをガチがきしてくのは、もちろんちゃんとやるときは意識して記述もしているしテストも実施している。 しかし、ぱぱっと記述を終えるには長すぎることあり、結局いつもコピペしている。

コピペだといつまでも成長しないので、できる限り、都度都度記述していくように切り替えて、記述に親しんでいきたい。

iptables関連のスクリプトはほんとみんな秘伝のタレになってるので、ちょっとそのままコピペで使うのはこわい。

そのまま実行するとIPアドレスが大量に列挙されて行数がとんでもないことになる。本当に辛い。

アドレス(と範囲)を列挙するなら ipsetつかったほうが楽。

今後拡大するネットワークと ipv6を控えて 秘伝のタレで運用するのは限界もありそうだよね。

まぁ、あれだnftablesに移行しろって事で。

arch見てたらこんな記述が

nftables は既存の iptables(ip-,ip6-)を置き換える netfilter のプロジェクトです。 カーネル 3.13 から nftables を使うことができます

nftables - ArchWiki

関連資料

ssh をiptablesで国内限定にする(日本国外のIPから規制する) - それマグで!

再起動時にipsetをリストアさせる方法: ままれのblog

https://github.com/BroHui/systemd-ipset-service

jid / json のjq的なクエリをインタラクティブに試せるツール

jid が便利そうなので使ってみた

jid-github

インストール

brew install jid

使ってみる

jid は json を食わせて、その結果から必要なものを絞り込んで調べることができる

試しに使ってみる。

echo '{"info":{"date":"2016-10-23","version":1.0},\
"users":[{"name":"simeji","uri":"https://github.com/simeji","id":1},\
{"name":"simeji2","uri":"https://example.com/simeji","id":2},\
{"name":"simeji3","uri":"https://example.com/simeji3","id":3}],"userCount":3}}' \
| jid

TAB で補完

TABキーを使うと候補が絞り込めて楽チン。

f:id:takuya_1st:20180819030947p:plain

検索だけなら jq より便利かも

jq は検索だけでなく、結合や計算や書き換えといった機能が豊富で、高機能すぎるので、どうしても複雑なところがあって直感的じゃない。

なので、このjidだと絞り込みはすごく楽だった。特定の配列をみたい時にはjid を使う方が早い

毎回ゼロからクエリ書くと面倒なので

cat test.json | jid '.info'

このように最初から引数値を与えることで、検索ができるようになっていて素晴らしい。

jq ように出力する

作ったクエリをjq として出したい時は

cat test.json | jid -q '.users'

のように作っておけば、jq に再利用が可能なクエリ文字列が出てきて便利だな。

キーボードの使い方

key description
TAB / CTRL + I Show available items and choice them
Enter 終了
CTRL + W Delete from the cursor to the start of the word
CTRL + U Delete whole query
CTRL + F / Right Arrow (:arrow_right:) Move cursor a character to the right
CTRL + B / Left Arrow (:arrow_left:) Move cursor a character to the left
CTRL + A To the first character of the 'Filter'
CTRL + E To the end of the 'Filter'
CTRL + J Scroll json buffer 1 line downwards
CTRL + K Scroll json buffer 1 line upwards
CTRL + G Scroll json buffer to bottom
CTRL + T Scroll json buffer to top
CTRL + L Change view mode whole json or keys (only object)
ESC Hide a candidate box

個人的には

個人的には、巨大なJSONファイルって読みにくいしメンテしにくいだけだから嫌いなんだけどなぜかみんな使うし、付き合うのは仕方ないよね。

参考資料

https://www.softantenna.com/wp/review/jid/

Cockpitでリモートからブラウザ経由でUbuntu /Debian GNU LinuxをWEBから管理する

cockpit を試してみて良かったのでめも

Cockpit は、Debian/Ubuntuなどで利用できる管理ツールで、Webブラウザから操作ができる。

ターミナルが使えたり

ブラウザからターミナルが使えたり

f:id:takuya_1st:20180818193339p:plain

daemon プロセスを再起動できたり

ブラウザからsystemd のプロセスを再起動できたり、

f:id:takuya_1st:20180818193420p:plain

モニタリング。

ディスクの使用量やCPUメモリの使用量を確認したり

f:id:takuya_1st:20180818195751p:plain

vm / docker のプロセスを管理

vm や Docker のコンテナをパパッと再起動したり状態をみたり

f:id:takuya_1st:20180818195310p:plain

systemd の依存関係をGUIで見れるから便利

ぐちゃぐちゃになるSystemdの依存関係や管理が資格的に行えるのはメリットがある。systemdのdaemonやタイマーの一覧して表示するのに便利だと思う。

f:id:takuya_1st:20180818195610p:plain

スマホから操作するのに便利。

ちょっとした再起動を試すのに、スマホからパパッとできるのでいいですね。

Cockpit プロジェクトをインストール

Debain 9 ( stretch ) には、Ubuntuと違ってBackportsで提供されていました

backports の導入とインストール

backportsの導入

echo 'deb http://deb.debian.org/debian stretch-backports main' > \
 /etc/apt/sources.list.d/backports.list
apt-get update

インストール

sudo apt-get install cockpit

起動

起動はsystemd socket で行われるので通常は使わなくていいらしい?

ポートとListenアドレスの指定

デフォルトでは、グローバルIPもローカルIPもローカルループバックアドレスもお構いなしにリッスンしてしまうので、ポートを決めておく。

cp /lib/systemd/system/cockpit.socket  /etc/systemd/
cat /etc/systemd/system/cockpit.socket
[Unit]
Description=Cockpit Web Service Socket
Documentation=man:cockpit-ws(8)
Wants=cockpit-motd.service

[Socket]
ListenStream= 127.0.0.1:9090
ExecStartPost=-/usr/share/cockpit/motd/update-motd '' localhost
ExecStartPost=-/bin/ln -snf active.motd /run/cockpit/motd
ExecStopPost=-/bin/ln -snf /usr/share/cockpit/motd/inactive.motd /run/cockpit/motd

[Install]
WantedBy=sockets.target

リロード

systemctl stop cockpit.socket
systemctl daemon-reload
systemctl start cockpit.socket

後は適当に認証する。

nginx とかApache で認証したり、vpnssh port forwarding 経由で使えばいいですよね。

ログイン画面

ログインは、ローカルユーザー( /etc/passwd ) で行うので、総当りされると面倒だし。安易にグローバルIPに公開できないですね。

f:id:takuya_1st:20180818193254p:plain

ssh 経由で認証したり、kerberos 認証したりもできるってさ

参考資料

https://cockpit-project.org/guide/latest/listen.html

https://cockpit-project.org/running#debian

ウェブブラウザーから操作できる軽量管理ツール「Cockpit」

gihyo.jp