http://www.kobore.net/soft/wstest4/go_server.mm.html
GOによる簡単なWebサーバの作り方
初版 2020/01/01
/home/kobore/www/soft/wstest4に一式あり
1.目的
2.サーバプログラム
3.クライアントプログラム
4.その他
GOによる簡単なWebSocketサーバの作り方
初版 2020/01/01
/home/kobore/www/soft/wstest32に一式あり
1.目的
2.課題
3.前提
4.サーバプログラム
5.クライアントプログラム
6.その他
GOによる簡単なWebSocketサーバの作り方 の"index.html"だけを変更して、ボタンを押すと全てのクライアントのコンテンツが同時に代わるように改造した。(文字表示はコメントアウトして消すこと)
稼働確認直後の、もっとも汚い状態のコードをアップしている。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>WebSocket Server</title> </head> <body> <input id="Button1" type="button" value="スタンバイ中" onclick="onButtonClick1();" /> <input id="Button2" type="button" value="待機中" onclick="onButtonClick2();" /> <input id="Button3" type="button" value="移動中" onclick="onButtonClick3();" /> <!-- <input id="input" type="text" /> --> <p id="input"></p> <p id="input1"></p> <p id="input2"></p> <p id="input3"></p> <!-- <button onclick="send()">Send</button> --> <!-- <pre id="output">outputのエリア</pre> --> <pre id="output"></pre> <!-- <img id="image_place" src="http://192.168.0.88:8686/red.html"/> <img id="image_place" src="http://192.168.0.88:8686/image3.jpg"/> --> <iframe id="image_place" src="http://192.168.0.88:8686/red.html" width="100%" height="700"></iframe> <script> var input1 = document.getElementById('input1'); var input2 = document.getElementById('input2'); var input3 = document.getElementById('input3'); var output = document.getElementById('output'); var socket = new WebSocket("ws://" + window.location.host + "/chat"); // 江端追記 // img要素を取得する var img = document.getElementById("image_place"); // 表示する画像番号 var idx = 1; // 江端追記ここまで socket.onopen = function() { // output.innerHTML += "Connection OK\n"; }; socket.onmessage = function(e) { // output.innerHTML += "Get message from server:" + e.data + "\n"; var obj = JSON.parse(e.data); // JSONオブジェクトに変換 // output.innerHTML += "Get object :" + obj.Message + "\n"; // 江端追記 //idx++; //if (idx > 3) { //idx = 1; //} //output.innerHTML += idx + "\n"; //output.innerHTML += "before\n"; // switch(e.data){ switch(obj.Message){ case '1': // console.log('1です'); // document.write("1です<br/>"); // document.getElementById("output").innerHTML += "1です"; // img.src = "http://kobore.net/soft/wstest32/image1.jpg"; // img.src = "http://192.168.0.88:8686/image1.jpg"; img.src = "http://192.168.0.88:8686/red.html"; break; case '2': // console.log('2です'); // document.write("2です<br/>"); // document.getElementById("output").innerHTML += "2です"; // img.src = "http://192.168.0.88:8686/image2.jpg"; img.src = "http://192.168.0.88:8686/yellow.html"; break; case '3': // console.log('3です'); // document.write("3です<br/>"); // document.getElementById("output").innerHTML += "3です"; // img.src = "http://192.168.0.88:8686/image3.jpg"; img.src = "http://192.168.0.88:8686/blue.html"; break; } // img要素のsrcに画像ファイル名を設定する //img.src = "image" + idx + ".jpg"; // img.src = "http://192.168.101.1:8686/image" + idx + ".jpg"; //img.src = "http://192.168.0.88:8686/image" + idx + ".jpg"; // output.innerHTML += "after\n"; // 江端追記ここまで }; //function send() { // socket.send(JSON.stringify( // { // message: input.value // } // )); // input.value = ""; //}; function onButtonClick1(){ input1.value = "1"; socket.send(JSON.stringify( { message: input1.value } )); input1.value = ""; }; function onButtonClick2(){ input2.value = "2"; socket.send(JSON.stringify( { message: input2.value } )); input2.value = ""; }; function onButtonClick3(){ input3.value = "3"; socket.send(JSON.stringify( { message: input3.value } )); input3.value = ""; }; </script> </body> </html>
"./static/red.html 等は、wstest4に入っている
Web画面の中央で「移動中」が点滅するhtmlを作って欲しいといったら、私の上司が作ってくれました。
以下を"blue.html"という名前で保存
<!DOCTYPE html> <html lang="ja"> <head> <link rel="stylesheet" type="text/css" href="blue-style.css"> <meta charset="utf-8"> </head> <body> <div class="central"> <div class="subtitle"> 移動中 </div> </div> </body> </html>
以下を"blue-style.css"という名前で保存
body { background: blue; color: white; overflow: hidden; } .central { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; width: 100%; font-size: 220px; font-weight: bold; -webkit-animation:blink 1.5s ease-in-out infinite alternate; -moz-animation:blink 1.5s ease-in-out infinite alternate; animation:blink 1.5s ease-in-out infinite alternate; } @-webkit-keyframes blink{ 0% {opacity:0;} 100% {opacity:1;} } @-moz-keyframes blink{ 0% {opacity:0;} 100% {opacity:1;} } @keyframes blink{ 0% {opacity:0;} 100% {opacity:1; }
忘れない内に記載しておく
まず、以下のプログラムを、main.go とかいう名前でセーブして、go build main.go をすると、 main という実行フィイルができる。
ところが、問題は、これを、任意のディレクトリから実行させようとすると、絶対パスの記載が必要となり、これを見つけるのに結構な時間がかかった。
結果としては、以下のようにすれば良いらしい(動いている)。
package main import ( "log" "net/http" ) func main() { http.Handle("/", http.FileServer(http.Dir("/home/pi/wstest4/static"))) if err := http.ListenAndServe(":8686", nil); err != nil { log.Fatal("ListenAndServe: ", err) } }
上記のプログラムを、"http:/localhost:8686/xxxxx.html"とブラウザに打ちこむと
/home/pi/wstest4/static/xxxxx.htmlのファイルが表示される
もしプログラムの http.Handle("/" を、http.Handle("/hogehoge" とすると、"http:/localhost:8686/hogehoge/xxxxx.html"と入力することで
/home/pi/wstest4/static/xxxxx.htmlのファイルが表示される
忘れない内に記載しておく
まず、以下のプログラムを、web-server.go とかいう名前でセーブして、go build web-server.go をすると、 web-server という実行フィイルができる。
ところが、問題は、これを、任意のディレクトリから実行させようとすると、絶対パスの記載が必要となり、これを見つけるのに結構な時間がかかった。
結果としては、以下のようにすれば良いらしい(動いている)。
func main() { // localhost:8080 でアクセスした時に index.html を読み込む //http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // http.ServeFile(w, r, "index.html") //}) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "/home/pi/wstest33/index.html") }) http.HandleFunc("/chat", HandleClients) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("error starting http server::", err) return } }
上記のプログラムを、"http:/localhost:8080/xxxxx.html"とブラウザに打ちこむと
/home/pi/wstest33/index.htmlのファイルが表示される
2つのサービスを作るのは美しくないが、もう色々考えるのが面倒なので、このまま強行
[Unit] Description = kanban daemon [Service] ExecStart = /home/pi/wstest4/main Restart = always Type = simple [Install] WantedBy = multi-user.target
を、/etc/systemd/system/kanban.serviceとして、保存し、
$ sudo systemctl enable kanban
でエントリして、
$ sudo systemctl start kanban
で、起動確認をする。
[Unit] Description = kanban-cont daemon [Service] ExecStart = /home/pi/wstest33/websocket-server Restart = always Type = simple [Install] WantedBy = multi-user.target
を、/etc/systemd/system/kanban-cont.serviceとして、保存し、
$ sudo systemctl enable kanban-cont
でエントリして、
$ sudo systemctl start kanban-cont
で、起動確認をする。
起動確認できていれば、sudo rebootで再起動する。
AWSを無料のSSLでなんとかしたい
初版 2020/01/25
(注)下記の情報は、適度に乱数化していますので、アタックは時間の無駄です
謝辞: 私のために、わざわざ手順書を作成してくれたSさんに感謝します。
1.SSL証明書とは何か
■知らん
しかし、AWS(Amazon Web Service)で、位置情報を取り扱うWebサイトを作るとき、この処理ができないと位置情報のやりとりができない(ブラウザの全部が、サービスを拒否する)ので、とにかく実装しなけれなならなくなった
■もう少し真面目に言うと
■何が美味しいのか
例えば、江端の運営している"kobore.net"が世界で唯一のホームページであることを、江端よりえらい人(機関、組織)に承認してもらうことで、"kobore.net"とあなたのPCやスマホのブラウザで暗号化通信がされることになる
つまり、"kobore.net"とあなたのPCやスマホの間での通信を、盗聴しようとしても、訳の分からん文字(情報)しか見えなくなる
この対応していないとどうなるか→ブラウザに「このサイト、信用できんぜ」と表示される
■で、分かると思うけど
2.やりたいこと
3. やってしまったこと
4.まず、AWSのSSL証明書を無効化する
(1)AWSのコンソールから、Certificate Managerにいって外そうとしたが、「証明書は *.sea-anemone.tech (a961fd79-546d-4915-bc6b-784decc76f3c)使用中で(他の AWS リソースに関連付けられていて)削除することはできません。リスト内の各リソースからその証明書との関連付けを解除し、もう一度お試しください。」と言われて失敗
(2)今度はELBの方にいってみる→リスナーのところにあるhttpsのリストを消去→この後、Certificate Managerにいって外したら成功した
(3)ところが、Webサービスが全滅してしまった
(4)ELBの方にいってみる→リスナーのところにあるhttpsのリストをhttp(80)を追加することで、復活した
5.では始める
Obtaining a new certificate Performing the following challenges: http-01 challenge for sea-anemone.tech http-01 challenge for www.sea-anemone.tech Using the webroot path /var/www/html for all unmatched domains. Waiting for verification... Cleaning up challenges Failed authorization procedure. sea-anemone.tech (http-01): urn:ietf:params:acme:error:dns :: No valid IP addresses found for sea-anemone.tech, www.sea-anemone.tech (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://www.sea-anemone.tech/.well-known/acme-challenge/XKDZnnDIn-Y7BZYkx4Q6dPbUVeaSDrKAMgEW6Y2iLHU: Connection refused
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/www.sea-anemone.tech/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/www.sea-anemone.tech/privkey.pem Your cert will expire on 2020-04-24. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
例えば、$sudo ls -l /etc/letsencrypt/live/www.sea-anemone.tech
-rw-r--r-- 1 root root 692 Jan 25 13:48 README lrwxrwxrwx 1 root root 42 Jan 25 13:53 cert.pem -> ../../archive/www.sea-anemone.tech/cert2.pem lrwxrwxrwx 1 root root 43 Jan 25 13:53 chain.pem -> ../../archive/www.sea-anemone.tech/chain2.pem lrwxrwxrwx 1 root root 47 Jan 25 13:53 fullchain.pem -> ../../archive/www.sea-anemone.tech/fullchain2.pem lrwxrwxrwx 1 root root 45 Jan 25 13:53 privkey.pem -> ../../archive/www.sea-anemone.tech/privkey2.pem
認証局に問い合わせをするのは、Webにアクセスあった時だから、認証局に上げるのは"変"
たぶん、EC2に証明書を閉じ込めておいても意味ないので、これをAWSの制御機能に渡す必要があるはず
sudo aws iam upload-server-certificate --server-certificate-name sea-anemone-certificate-20200125 --certificate-body file:///etc/letsencrypt/live/www.sea-anemone.tech/cert.pem --private-key file:///etc/letsencrypt/live/www.sea-anemone.tech/privkey.pem
$ sudo aws iam upload-server-certificate --server-certificate-name sea-anemone-certificate-20200125 --certificate-body file:///etc/letsencrypt/live/www.sea-anemone.tech/cert.pem --private-key file:///etc/letsencrypt/live/www.sea-anemone.tech/privkey.pem --certificate-chain file:///etc/letsencrypt/live/www.sea-anemone.tech/chain.pem --path /www.sea-anemone.tech/
SERVERCERTIFICATEMETADATA arn:aws:iam::924297495837:server-certificate/www.sea-anemone.tech/sea-anemone-certificate-20200125 2020-04-24T03:53:05Z /www.sea-anemone.tech/ ASCA5ONDMQUO2ZNB6MV7H sea-anemone-certificate-20200125 2020-01-25T07:25:10Z
6.確認方法
以上
sshなどでリモートログインを可能にしている場合、ユーザのログイン履歴を調る方法
$ last [ユーザ名] ・・・ ログイン履歴を表示する。
$ lastlog [ユーザ名] ・・・ システムに登録された各ユーザの最終ログイン履歴を表示する。
$ lastb [ユーザ名] ・・・ ユーザのログイン失敗履歴を表示する。
出展 https://horus531.hatenadiary.org/entry/20110103/1294058791