2020/09,江端さんの忘備録

(昨日の続きです)

(Continuation from yesterday)

攻撃されない為には、セキュリティ対策が重要なのは言うまでありません。

It goes without saying that security measures are important to avoid being attacked.

定期的なセキュリティパッチの更新、ウイスルチェック、不審なメールを開かない、パスワードを定期的に更新する、などの ――

Regularly updating security patches, checking whistles, not opening suspicious emails, updating passwords on a regular basis, etc.

コロナ禍における、「マスク」「手洗い」「3密回避」というような基本的なことが、最強の対策です。

The most powerful countermeasures against corona ravages are basic things such as masks, washing hands, and avoiding the three densities.

さらに、これに加えて、「人から恨みを買わないようにする」とか「穏当な発言を行うようにする」とか「敢えて敗北を装う」などの ――

Furthermore, in addition, "do not buy grudges from people", "make moderate statements", "dare to pretend to be defeated", etc.

そういう、普段のアナログ対応も、サイバー攻撃対策では、結構大切だったりします。

That kind of everyday analog response is also quite important in preventing cyber attacks.

-----

私のモットーは、

My motto is

『どんなに正論吐こうとも、自宅を燃やされたら負けだ』

"No matter how much of a good argument you have, you'll lose if they burn your house down"

です。

ただし、このモットーは

However, this motto is from

『例え逮捕されることになろうとも、奴をやっつけてしてスッキリしたい』

"I'd feel better about killing him, even if it meant getting myself arrested"

という、私のネガティブな感情から導かれていること(そして、実績もあること)に、皆さんは留意しておくべきです。

You should all keep in mind that the above phrase comes from my negative feelings (my track records).

2020/09,江端さんの忘備録

先日、図書館で、FBIだかCIAだかにハッキングをしかけるハッカーの小説を借りて読んでいたのですが、途中で挫折しました。

The other day I was at the library reading a novel about a hacker who tries to hack into the FBI or the CIA, but I failed to read it in the middle of the book.

『勉強不足にも程があるんじゃないか』

"Too little study"

というほど、稚拙な内容でした。

I was afraid that it was so poorly written.

「この程度の内容にしなければ、読者がついてきてくれない」という、ビジネス上の計算もあるのかもしれない ―― という善意の解釈は、直ちに却下できました。

"Maybe there's a business calculation that says, "If I don't make this level of content, my readers won't follow me", however I immediately rejected such a good-faith interpretation of mine.

そういうディテールに関わる知識や知見は、どうしても「行間に現われてきてしまう」ものであって、どんなに抑えていても見えてしまうものなのです。

That kind of detail-related knowledge inevitably "shows up between the lines". No matter how much they try to suppress it, I can still see it.

-----

現実のサイバー攻撃では、"暴力"やら"銃"やら"拉致"やら"誘拐"やら、そんなものは登場しません。

There are no "violence" or "guns" or "abduction" or "kidnapping" or "kidnapping" in real life cyber attacks.

現実のサイバー攻撃を映画にすれば、

If you make a movie about a real-life cyber attack,

―― ずーっとPCに向きあって、ディスプレイ上に展開された20くらいのコンソールを、同時に操作するアタッカーが、延々20時間くらい作業し続ける

"An attacker facing the PC and operating 20 or so consoles spread out on the display at the same time, working for about 20 hours on end."

というものになるはずです。

つまらない、退屈な映画になるでしょう。

It will be a boring, boring movie.

-----

サイバー攻撃は、当然ですが、攻撃者に対して防御者が圧倒的に不利です。

Cyber attacks, of course, put the defender at a tremendous disadvantage against the attacker.

色々言われていますが、「狙われたら"おしまい"」です。

There's a lot of talk about it, but it's all over if you're targeted.

攻撃側は、複数の人数が潤沢な時間とリソースをつかって任意の時間に攻撃できますが、防御側は、24時間休むことなく、一箇所で対応し続けなければならないからです。

An attacker can have multiple people attacking at any given time with plenty of time and resources, however, the defenders must continue to respond in one place, 24 hours a day, without a break.

だからこそ、私は「自動報復システム」という特許出願をしようとしたんですけどね。止められましたが。

That's why I tried to file a patent application called "Automatic Retaliation System", however I was stopped.

(続く)

(To be continued)

2020/09,江端さんの忘備録

インターネットは、情報の宝庫ですが、同時にデタラメの宝庫でもあります。

The Internet is a treasure trove of information, but it is also a treasure trove of bullshit.

まあ、そりゃ仕方がないと思います。

Well, I guess I can't help it.

正確に書く"義務"がある訳ではありませんから。

There is no "obligation" to be precise.

検索エンジンが、その記事の内容の正確性まで評価してくれると良いのですが、それは無理でしょう。

It would be nice if search engines would even rate the accuracy of the content of the article, but they can't do that.

-----

知らない人も多いと思いますが、「内閣府や省庁が発表している資料」は良くできています。

Many people don't know this, but the "documents published by the Cabinet Office and ministries" are well done.

政策を推進する主体なので、政策に阿(おもね)る内容となるのは当然です。

Since they are the body that promotes policy, it is only natural that the content would be too much for the policy.

しかし、出てくるデータは、そこらの企業やライターでは手に入れることができないものばかりです。

However, the data that comes out is not available to those companies and writers.

また、情報公開請求すれば、大抵の情報は出してくれます(時間かかりますけど、お金は安いです(500円くらいから))。

Also, if you request a release of information, they will give you most of the information (it takes some time, but it's cheap (about $500)).

-----

まあ、そうやって、得られたデータを駆使して一生懸命コラム書いても、多くの人は「数字」に興味を向けてくれないんですよね。

Well, no matter how I write a column so hard with the data I got, not many people are interested in the "numbers".

これは、多くの人にとって、「数字」は「嫌な思い出」とセットメニューになっているからかもしれません。

This may be because, for many people, "numbers" are on the set menu with "bad memories".

テストとか、学業成績とか、ノルマとか、営業利益とか ―― そりゃ、楽しい思い出になろう訳がありません。

Tests, academic performance, quotas, operating profits -- that can't be a pleasant memory.

-----

まあ、インターネットの投稿掲示板なんかに、統計値とかデータが記載されたら、「正しい情報」へのアプローチにはなるでしょうが、『一瞬で盛り下がるだろうな』と予想できます。

Well, I suppose it would be an approach to "correct information" if statistics and data were included in an internet posting board or something, however I can predict that it will be instantly quiet.

2020/09,江端さんの忘備録

先日、国勢調査の調査票を配布している人が来ました。

A few days ago, the person distributing the census questionnaire came to my home.

私は、政府のデータを山程使わせて貰っている身の上ですので、調査に協力するのは当然だと思っています。

I am the one who has been allowed to use a mountain of government data, so I think it's only natural for me to cooperate with the investigation.

パソコンから入力できる、というのも助かりました。

The fact that I can enter the information from my computer was also helpful.

ただ、今回の調査を見て分かったことは ―― この調査表に、デタラメ書いても分からない ―― ということですね。

But what we've learned from this investigation is that nobody can write bullshit on these charts.

正確性を担保したいのであれば、マイナンバーカードの電子署名などをベースにすべきでしょうが、当然、そんなことをすれば、応答率が下がるのは目に見えています。

If they want to ensure accuracy, it should be based on things like the electronic signature on "MY NUMBER CARD", but of course, if they do that, we will reject to answer it.

だから、この調査方法で正しいのだと思います。

So I think they are correct in this survey method.

-----

娘たちの高校や大学の所在地の住所とかも入っていましたが、私、長女の大学の所在地、知らなかったんですよね。

I even entered the addresses of my daughters' high school and college locations, but I didn't know where my senior daughter's college was.

『おお、あの大学、そんなオシャレな"区名"のところにあるのか、 ―― 生意気な』と思いながら、入力していました。

I thought to myself, "Oh, they college is in that fashionable ward name - that's cheeky".

なにしろ、入学式の時に、一回入構しただけでしたので。

After all, I only entered the school once during the entrance ceremony.

私の方は、勤務先の入力で迷いました ―― 「ここ数ヶ月にかぎれば"自宅"だよなぁ」と、まあ、そんなことを考えながら入力していました。

I've been wondering how to enter the company I work for. "Only in the past few months, it's been "home"". Well, I was thinking about that with typing.

所要時間は、5分くらいです。

It takes about 5 minutes.

会社で行われているJMIとか、その他のアンケートに比べると、実に良心的です。

It's really quite conscientious compared to the JMI and other surveys conducted by the company.

皆さんも、我が国の為 ―― ではなく、私のコラムの資料の為に、ご協力をお願い致します。

I would like to ask you all to help, not for the sake of our country, but for the sake of the material in my column.

2020/09,江端さんの忘備録

「やはり俺の青春ラブコメは間違っている完」の第11話の視聴後感想になります。

This is my impression after watching episode 11 of "My Youth Romantic Comedy is Wrong,As I Expected -- Final"

-----

ああ、なるほど ――

Oh, I see...

主人公はかっこをつけたくて、「言葉では表現できない」とか「一言程度で伝わるかよ」と言っているんじゃないんだ、と分かりました。

I could tell that the main character wasn't trying to be cool by saying, "I can't express myself in words" or "I don't think a single word can convey my feelings.

「好きだ」とか「愛している」程度の言葉では、"表わせない想い"というのは ―― 本当にあるんです。

I know that there are feelings that cannot be expressed in words like "I love you"

でも、そのことに私が気がついたのは、ティーンエイジャーから、随分月日が経過してからでした。

But when I noticed that, it's been a long time since I was a teenager.

だから、『この主人公、怖い奴だな』と思いました。

That's why I thought, "this hero is a scary guy"

もしかしたら、この主人公、実年齢はすでに「老齢」に達しているんじゃないか、と思った程です。

I wondered if this hero, the actual age, had already reached "old age".

2020/09,江端さんの忘備録

私が、研究所の特許業務で、20年以上も「パワハラの当事者」であったことは、ここに記載しています。

It is stated here that I have been a "participant in power harassment" for more than 20 years in the patent business of the laboratory.

で、まあ、このコラムで、

Well, in this column, I am developing the theory of

「我々は、だれもがパワハラの加害者になることからは逃げられない」

"We cannot escape from being the perpetrator of power harassment."

という論を展開しています。

私は、別に、「パワハラを一般化して、自己弁護をする」という意図はありません。

I have no intention of "generalizing power harassment and defending myself".

ただ、パワハラの当事者は、全員、「自分がパワハラをしている」などということを夢にも思っていないということです。

However, all the parties to power harassment do not dream of "I am doing power harassment".

-----

最近、私、量子論的思想にすっかり汚染されていますが ――

Recently, I have been completely contaminated with quantum theory.

『我々は、その存在が「パワハラ」と「非パワハラ」が併存している状態にある』

"We are in a state where" power harassment "and" non-power harassment "coexist"

『しかし、その存在を「パワハラ」と観測した瞬間、その人間は「パワハラ」を行う人間として確定する』

"However, the moment we observe its existence as "power harassment", that person is confirmed as a person who performs "power harassment""

ということです。

だから、不愉快な上司には、「パワハラだ!」と叫ぶことで、その状態を確定させられます。

Therefore, you can label your unpleasant boss by yelling "Power harassment!".

さらに、社内のコンプライアンス機関や、訴訟によって、その人の「パワハラ」を社会的にも認定させましょう。

In addition, the person's "power harassment" can be socially recognized by an in-house compliance agency or a lawsuit.

-----

逆に言えば、「パワハラだ!」その一言で、その人がパワハラであることは、確定し、もうその状態を変えることはできなくなります。

Conversely, "She/he will do power harassment!" with that one word, it is confirmed that the person is power harassment, and it can no longer be changed.

だから、そこの一言は濫用してはなりません。

So we don't have to abuse that word.

ただ、必要な場合には、行使しなければなりません ―― 世界で一番大切なものは自分自身だからです。

But if you need it, you have to exercise it. Because the most important thing in the world is myself.

-----

で、私は、『特許業務のパワハラメーカ』ということで、確定しています。

So, I have been confirmed as a "power harassment maker for patent business".

2020/09,江端さんの忘備録,江端さんの技術メモ

私が今使っているWordPressは、現時点での最新バージョンなのですが、どうしても、Prism For WPのメニューが出てこなくて、ずっと悩んでいました。

で、色々しらべた結果、

をインストールする必要があるらしく、これを入れることでメニューがでるようになりました。

が今度は、画像イメージのコピペができなくなりました。

で、さらに、

をインストールして、この画面のようにコピペを張りつけるように戻すことができるようになりました。

なんか、やりたいことを実現していくと、どんどんWordPressのダウングレードをしているような気になってきました(プラグインもどんどん入れることになって、気持ち悪いです(経験上、プラグインの入れすぎは、トラブルの元になります))。

 

2020/09,江端さんの技術メモ

常日頃から御指導頂いているSさんから、Bad Elf 2300の位置情報をキャプチャするhtmlファイルの内容を教えて頂いた。忘れないように、残しておく。
Bad ElfをBTでリンクしたiPadで稼働を確認済み(iPhoneでは稼働確認できなかった)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>geolocation-sample</title>
</head>
<body>
  <div id="output"></div>
 
<script>
    var output = document.getElementById('output');
 
    // 位置情報の取得に成功した際のコールバック
    const successCallback = (position) => {
        console.log(position);
		output.innerHTML += "<P>==========";
		output.innerHTML += "<P>time:" + position.timestamp;
		output.innerHTML += "<P>latitude:" + position.coords.latitude;
		output.innerHTML += "<P>longitude:" + position.coords.longitude;
		output.innerHTML += "<P>altitude:" + position.coords.altitude;
		output.innerHTML += "<P>accuracy:" + position.coords.accuracy;
		output.innerHTML += "<P>altitudeAccuracy:" + position.coords.altitudeAccuracy;
		output.innerHTML += "<P>heading:" + position.coords.heading;	
		output.innerHTML += "<P>speed:" + position.coords.speeed;	
    };
 
    // 位置情報の取得に失敗した際のコールバック
    const errorCallback = (err) => {
        console.log(err);
		output.innerHTML += "Error\n";		
    };
 
    // 位置を監視する構成オプション
    // オプションの内容は次のリンクに書かれています。
    // https://developer.mozilla.org/ja/docs/Web/API/PositionOptions
    const options = {
        enableHighAccuracy: true,
        timeout: 5000,
        maximumAge: 0
    };
 
    let watchPositionID;
 
    window.onload = () => {
        // navigator.geolocation.watchPositionについては次のURLにかかれています。
        // https://developer.mozilla.org/ja/docs/Web/API/Geolocation/watchPosition
        watchPositionID = navigator.geolocation.watchPosition(successCallback, errorCallback, options);
    };
 
    // ブラウザーを閉じる前に位置の監視を止めます
    window.onbeforeunload = () => {
        navigator.geolocation.clearWatch(watchPositionID);
    }
</script>
</body>
</html>

2020/09,江端さんの忘備録

私、当時の情報処理試験の「情報処理第1種」と「ネットワークスペシャリスト」の合格者です。

I am a qualification holder of "Information Processing Type 1" and "Network Specialist" of the old information processing test.

勿論、これらの資格も、TOEICのスコアと同様に、現場で使えないのであれば、何の意味もないものです。

Of course, these qualifications, like the TOEIC score, have no meaning if they cannot be used in the field.

もちろん、履歴書に記載事項を増やせたり、他の試験の免除などのメリットもあります。

Of course, there are also benefits such as increasing the number of items in the resume and exemption from other exams.

しかし、最近は、この手の資格試験の興味は失せ、私の人生には「ハレ」がありません。

These days, however, I've lost interest in these types of certification exams and there is no "hare" in my life.

-----

以前、嫁さんが派遣会社からの要請で「パソコン検定」の勉強をしていたことがあります。

Previously, my wife had been studying "PC certification" at the request of a temporary staffing agency.

その時、私は、嫁さんの家庭教師をしていました。

At that time, I was a tutor for my wife.

なにしろ、私は、その「パソコン検定」の教科書の"記載ミス"を指摘できるレベルのITエンジニアですから。

After all, I'm an IT engineer at a level that can point out "statement mistakes" in the "PC certification" textbook.

-----

江端:「私も、この『パソコン検定』受験してみようかな」

Ebata: "I wonder if I would take this "PC certification test".

嫁さん:「なんで?」

Wife: "Why?"

江端:「なんか、こう、"ハレ"が欲しくて」

Ebata: "Somehow, I want "hare"".

と言ったら ―― かなりマジな感じで怒られました。

When I said that, my wife made me angry with a serious feeling.

『我が家には、そういう金は1円もない!』と言われました。

She said that "there is no such money in my house!".

-----

それはさておき。

Aside from that.

「エンベデッドシステムスペシャリスト試験(ES)」というのを、今日、始めて見つけました。

I just found the "Embedded Systems Specialist Exam (ES)" for the first time today.

これだったら、ちょっと勉強してみようかな、という気になってきました。

If I'm taking this exam, I think I'm going to study a bit more.

EtherCATやら、ラズパイが出題範囲に入っているのかな、とか考えて、過去問を調べてみました。

I wondered if EtherCAT and Raspberry Pi were in the scope of the questions, so I checked the past questions.

流石にそういうものはなかったようですが、午後の試験は、これまでの仕事の案件と「丸被り」していて、苦笑いしていました。

As expected, there didn't seem to be any such thing. However, the afternoon's exam question was "almost the same system" as my previous work projects, and I was chuckling.

2020/09,江端さんの忘備録,江端さんの技術メモ

https://www.prakharsrivastav.com/posts/from-http-to-https-using-go/ が原典

Goを使ってHTTPからHTTPSへ
2019-08-02 :: プラカール・スリバスタフ

序章
この記事では、Go で TLS 暗号化を設定する方法を学びます。さらに、相互にTLS暗号化を設定する方法を探っていきます。このブログ記事で紹介されているコードはこちらからご覧いただけます。この記事では、関連するスニペットを表示しています。興味のある読者は、リポジトリをクローンしてそれに従ってください。

まず、シンプルな Http サーバとクライアントを Go で書くことから始めます。次に、サーバで TLS を設定することで、両者間のトラフィックを暗号化します。この記事の最後に、両者間の相互 TLS を設定します。

シンプルなhttpサーバー
まず、Go で Http クライアント・サーバの実装を作成してみましょう。localhost:8080 に到達可能な Http エンドポイント /server を公開します。そして、http.Clientを使ってエンドポイントを呼び出し、その結果を表示します。

完全な実装はこちらを参照してください。

// Server code
mux := http.NewServeMux()
mux.HandleFunc("/server", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprint(w, "Protect Me...")
})
log.Fatal(http.ListenAndServe(":8080", mux))


// Client code
if r, err = http.NewRequest(http.MethodGet, "http://localhost:8080/server", nil); err != nil {
	log.Fatalf("request failed : %v", err)
}

c := http.Client{
	Timeout:   time.Second * 5,
	Transport: &http.Transport{IdleConnTimeout: 10 * time.Second},
}

if data, err = callServer(c, r); err != nil {
	log.Fatal(err)
}
log.Println(data) // Should print "Protect Me..."

次のセクションでは、TLS を使用してクライアントとサーバ間のトラフィックを暗号化します。その前に、公開鍵インフラストラクチャ (PKI) をセットアップする必要があります。

PKI のセットアップ
ミニ PKI インフラストラクチャをセットアップするために、minica という Go ユーティリティを使用して、ルート、サーバ、クライアントの鍵ペアと証明書を作成します。実際には、認証局 (CA) またはドメイン管理者 (組織内) が鍵ペアと署名付き証明書を提供してくれます。私たちの場合は、minicaを使ってこれをプロビジョニングしてもらうことにします。

鍵ペアと証明書の生成
注: これらを生成するのが面倒に思える場合は、Github リポジトリでコミットされた証明書を再利用することができます。

以下の手順で証明書を生成します。

minicaをインストールする: github.com/jsha/minicaを取得してください。
minica --domains server-certを実行してサーバ証明書を作成します。
初めて実行すると4つのファイルが生成されます。
minica.pem(ルート証明書
minica-key.pem (root 用の秘密鍵)
server-cert/cert.pem (ドメイン「server-cert」の証明書、ルートの公開鍵で署名されています)
server-cert/key.pem (ドメイン「server-cert」の秘密鍵)
minica --domains client-certを実行してクライアント証明書を作成します。2つの新しいファイルが生成されます。
client-cert/cert.pem (ドメイン "client-cert "の証明書)
client-cert/key.pem (ドメイン "client-cert "の秘密鍵)
また、minicaでドメインの代わりにIPを使用して鍵ペアや証明書を生成することもできます。

etc/hosts にエイリアスを設定する
上記で生成したクライアント証明書とサーバ証明書は、それぞれドメイン server-cert と client-cert で有効です。これらのドメインは存在しないので、localhost(127.0.0.1)のエイリアスを作成します。これを設定すると、localhost の代わりに server-cert を使用して Http サーバにアクセスできるようになります。

Linux以外のプラットフォームを使っている場合は、OSに合わせた設定方法をググってみてください。私はLinuxマシンを使っていますが、ドメインエイリアスの設定はとても簡単です。etc/hostsファイルを開き、以下の項目を追加します。

127.0.0.1       server-cert
127.0.0.1       client-cert

この時点で、インフラストラクチャの設定は完了です。次のセクションでは、クライアントとサーバ間のトラフィックを暗号化するために、これらの証明書を使ってサーバを設定します。

サーバーでTLSを設定する
サーバ-certドメインに生成された鍵と証明書を使って、サーバにTLSを設定してみましょう。クライアントは先ほどと同じです。唯一の違いは、3つの異なるURLでサーバを呼び出すことで、何が起こっているのかを理解することです。

完全な実装はこちら

// Server configuration
mux := http.NewServeMux()
mux.HandleFunc("/server", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "i am protected")
})
log.Println("starting server")
// Here we use ListenAndServerTLS() instead of ListenAndServe()
// CertPath and KeyPath are location for certificate and key for server-cer
log.Fatal(http.ListenAndServeTLS(":8080", CertPath, KeyPath, mux))

// Server configuration
c := http.Client{
    Timeout:   5 * time.Second,
    Transport: &http.Transport{IdleConnTimeout: 10 * time.Second,},
}

if r, err = http.NewRequest(http.MethodGet, "http://localhost:8080/server", nil); err != nil { // 1
//if r, err = http.NewRequest(http.MethodGet, "https://localhost:8080/server", nil); err != nil { // 2
//if r, err = http.NewRequest(http.MethodGet, "https://server-cert:8080/server", nil); err != nil { // 3
    log.Fatalf("request failed : %v", err)
}

if data, err = callServer(c, r); err != nil {
    log.Fatal(err)
}
log.Println(data)

http.ListenAndServeTLS()を使用してサーバを起動します。これにはポート、公開証明書へのパス、秘密鍵へのパス、そしてHttp-handlerの4つの引数が必要です。サーバからのレスポンスを見てみましょう。私たちは失敗しますが、私たちはどのようにHttp暗号化が動作するかについてのより多くの洞察を与える3つの異なる要求を送信します。

Attepmt 1 http://localhost:8080/server に送信すると、応答があります。

Client Error. Get http://localhost:8080/server: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03x01x00x02\x02"

サーバエラー: http: 127.0.0.1:35694 からの TLS ハンドシェイクエラー: tls: 最初のレコードが TLS ハンドシェイクのように見えません。

これは、サーバーが暗号化されたデータを送信していることを意味する良いニュースです。Http経由では誰も意味をなさないでしょう。

Attempt 2 to https://localhost:8080/server、レスポンスは以下の通りです。

クライアントエラーです。Get https://localhost:8080/server: x509: certificate is valid for server-cert, not localhost

サーバエラー: http: 127.0.0.1:35698 からの TLS ハンドシェイクエラー: リモートエラー: tls: 不正な証明書

これはまたしても朗報です。これは、ドメインサーバ証明書に発行された証明書を他のドメイン(ローカルホスト)で使用することができないことを意味します。

Attempt 3 to https://server-cert:8080/server、応答があります。

クライアントエラーです。Get https://server-cert:8080/server: x509: certificate signed by unknown authority

サーバエラー: http: 127.0.0.1:35700 からの TLS ハンドシェイクエラー: リモートエラー: tls: 不正な証明書

このエラーは、クライアントがその証明書に署名したことを信頼していないことを示しています。クライアントは証明書に署名した CA を認識していなければなりません。

このセクションの全体的な考えは、TLS が保証する 3 つの保証を実証することでした。

メッセージは常に暗号化されている。
サーバが実際に言っている通りのものであること。
クライアントはサーバの証明書を盲目的に信じてはいけない。クライアントは、CA を通じてサーバの身元を確認できるようにしなければなりません。

クライアントでCA証明書を設定する
クライアント側のCA証明書を設定して、ルートCAの証明書とサーバの身元を照合できるようにします。サーバ証明書はルートCAの公開鍵を使って署名されているので、TLSハンドシェイクが有効になり、通信が暗号化されます。

完全な実装はこちらにあります。

// create a Certificate pool to hold one or more CA certificates
rootCAPool := x509.NewCertPool()

// read minica certificate (which is CA in our case) and add to the Certificate Pool
rootCA, err := ioutil.ReadFile(RootCertificatePath)
if err != nil {
    log.Fatalf("reading cert failed : %v", err)
}
rootCAPool.AppendCertsFromPEM(rootCA)
log.Println("RootCA loaded")

// in the http client configuration, add TLS configuration and add the RootCAs
c := http.Client{
    Timeout: 5 * time.Second,
    Transport: &http.Transport{
        IdleConnTimeout: 10 * time.Second,
        TLSClientConfig: &tls.Config{RootCAs: rootCAPool},
    },
}

if r, err = http.NewRequest(http.MethodGet, "https://server-cert:8080/server", nil); err != nil {
    log.Fatalf("request failed : %v", err)
}

if data, err = callServer(c, r); err != nil {
    log.Fatal(err)
}
log.Println(data)

// server response
prakhar@tardis (master)? % go run client.go  
RootCA loaded
i am protected # response from server

これにより、先ほど説明した3つの保証がすべて保証されます。

相互TLSの設定
サーバーにクライアントの信頼を確立しています。しかし、多くのユースケースでは、サーバーがクライアントを信頼する必要があります。例えば、金融、医療、公共サービス業界などです。これらのシナリオのために、クライアントとサーバーの間で相互にTLSを設定して、双方がお互いを信頼できるようにします。

TLSプロトコルは、最初からこれをサポートしています。相互TLS認証を設定するために必要な手順は以下の通りです。

1.サーバはCA(CA-1)から証明書を取得します。クライアントは、サーバの証明書に署名したCA-1の公開証明書を持っている必要があります。
2.クライアントは CA (CA-2) から証明書を取得します。サーバは、クライアントの証明書に署名したCA-2の公開証明書を持っていなければなりません。簡単にするために、クライアント証明書とサーバ証明書の両方に署名するために同じ CA (CA-1 == CA-2) を使用します。
3.サーバは、すべてのクライアントを検証するためにCA証明書プールを作成します。この時点で、サーバはCA-2の公開証明書を含む。
4.同様に、クライアントは独自のCA証明書プールを作成し、CA-1の公開証明書を含む。
5.両者は、CA 証明書プールに対して受信要求を検証します。どちらか一方に検証エラーがあった場合、接続は中断されます。
実際に動作を見てみましょう。この機能の完全な実装はこちらを参照してください。

サーバーの設定

mux := http.NewServeMux()
mux.HandleFunc("/server", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "i am protected")
})

clientCA, err := ioutil.ReadFile(RootCertificatePath)
if err != nil {
    log.Fatalf("reading cert failed : %v", err)
}
clientCAPool := x509.NewCertPool()
clientCAPool.AppendCertsFromPEM(clientCA)
log.Println("ClientCA loaded")

s := &http.Server{
    Handler: mux,
    Addr:    ":8080",
    TLSConfig: &tls.Config{
        ClientCAs:  clientCAPool,
        ClientAuth: tls.RequireAndVerifyClientCert,
        GetCertificate: func(info *tls.ClientHelloInfo) (certificate *tls.Certificate, e error) {
            c, err := tls.LoadX509KeyPair(CertPath, KeyPath)
            if err != nil {
                fmt.Printf("Error loading key pair: %v\n", err)
                return nil, err
            }
            return &c, nil
        },
    },
}
log.Fatal(s.ListenAndServeTLS("", ""))

この設定で注意すべき点がいくつかあります。

  1. http.ListenAndServeTLS() の代わりに server.ListenAndServerTLS() を使用します。
  2. サーバ証明書と鍵を tls.Config.GetCertificate 関数の中にロードします。
  3. サーバが信頼すべきクライアント CA 証明書のプールを作成します。
  4. tls.Config.ClientAuth = tls.RequireAndVerifyClientCertを設定し、接続しようとするすべてのクライアントの証明書を常に検証します。検証されたクライアントのみが会話を続けることができます。

クライアント設定
http.Clientの設定は、クライアントの設定も少し変わります。

rootCA, err := ioutil.ReadFile(RootCertificatePath)
if err != nil {
    log.Fatalf("reading cert failed : %v", err)
}
rootCAPool := x509.NewCertPool()
rootCAPool.AppendCertsFromPEM(rootCA)
log.Println("RootCA loaded")

c := http.Client{
    Timeout: 5 * time.Second,
    Transport: &http.Transport{
        IdleConnTimeout: 10 * time.Second,
        TLSClientConfig: &tls.Config{
            RootCAs: rootCAPool,
            GetClientCertificate: func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
                c, err := tls.LoadX509KeyPair(ClientCertPath, ClientKeyPath)
                if err != nil {
                    fmt.Printf("Error loading key pair: %v\n", err)
                    return nil, err
                }
                return &c, nil
            },
        },
    },
}

サーバと比較した場合の設定の違いに注目してください。

  1. tls.Configでは、サーバー上のClientCAの設定に対して証明書プールをロードするためにRootCAを使用しています。
  2. tls.Config.GetClientCertificate を使用して、サーバー上の tls.Config.GetCertificate に対してクライアント証明書をロードしています。
  3. GitHub の実際のコードにはいくつかのコールバックがあり、これを使って証明書の情報を見ることもできます。

クライアントとサーバの相互TLS認証の実行

# Server logs
2019/08/01 20:00:50 starting server
2019/08/01 20:00:50 ClientCA loaded
2019/08/01 20:01:01 client requested certificate
Verified certificate chain from peer:
  Cert 0:
    Subject [client-cert] # Server shows the client certificate details
    Usage [1 2]
    Issued by minica root ca 5b4bc5 
    Issued by 
  Cert 1:
    Self-signed certificate minica root ca 5b4bc5

# Client logs
2019/08/01 20:01:01 RootCA loaded
Verified certificate chain from peer:
  Cert 0:
    Subject [server-cert] # Client knows the server certificate details
    Usage [1 2]
    Issued by minica root ca 5b4bc5
    Issued by 
  Cert 1:
    Self-signed certificate minica root ca 5b4bc5
2019/08/01 20:01:01 request from server
2019/08/01 20:01:01 i am protected

結論
TLS の設定は、実装の問題というよりも証明書の管理の問題が常にあります。TLS 設定における典型的な混乱は、実装というよりも正しい証明書の使用に関連していることが多いです。TLS プロトコルとハンドシェイクを正しく理解していれば、Go は箱から出してすぐに必要なものをすべて提供してくれます。

また、理論的な観点からTLSの暗号化とセキュリティを探求した以前の記事もチェックしてみてください。

参考文献
この記事は、Gophercon-2018でのLiz Riceの素晴らしいトークに大きく影響されていますので、ぜひチェックしてみてください。その他の参考文献は以下の通りです。

secure-connections: gophercon のためのレポ
minica 認証局
Eric Chiangによるこの驚くべき記事。必読です。
step-by-step-guide-to-mtls-in-go.
mediumのこの記事。