動的言語しかやったこと無い私ですが、ひょんなことからGoにふれてみることにしました。
まだ、チュートリアルを読んだり、Effective Goを読んでみたりのレベルですが・・・
環境
- CentOS6.7
- Go 1.5.2
参考にしたサイト
- golang の HTTPS サーバで StartSSL の無料 SSL 証明書を使うには
- GoのHTTPサーバーを80番や443番ポートでListenする方法を調べた
- オレオレ証明書をopensslで作る(詳細版)
- Build web application with Golang
まずはオレオレ証明書を作ってみる
証明書無いと動かないのでオレオレ証明書をopensslで作る(詳細版)を参考に証明書を作成
$ openssl genrsa 2048 > myself.key
$ openssl req -new -key myself.key > myself.csr
$ openssl x509 -days 3650 -req -signkey myself.key < myself.csr > myself.crt
$ mkdir -p ssl/development/
$ mv myself.crt ssl/development
$ mv myself.key ssl/development
Goでhttpsサーバーを書く
mainの一行(http.ListenAndServeTLS(":50124", "ssl/development/myself.crt", "ssl/development/myself.key", nil)
)で作成したオレオレ証明書を食わせてます。今回はログインを想定した内容でフォームの値を確認するところまで記載しています。GoのHTTPSサーバー自体のポートは50124で起動するようにしています
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //リクエストを取得するメソッド
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, nil)
} else {
r.ParseForm()
//ログインデータがリクエストされ、ログインのロジック判断が実行されます。
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
}
}
func main() {
http.HandleFunc("/login", login) //アクセスのルーティングを設定します
err := http.ListenAndServeTLS(":50124", "ssl/development/myself.crt", "ssl/development/myself.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
以下ログインフォームのテンプレート
<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
ユーザ名:<input type="text" name="username">
パスワード:<input type="password" name="password">
<input type="submit" value="ログイン">
</form>
</body>
</html>
SSLってポート443じゃ???
今回はrootではないユーザーでgoのHTTPSサーバーを起動させることを想定していますので、root以外のユーザーだとポート1024以上ではないとポートをlistenできないので、GoのHTTPサーバーを80番や443番ポートでListenする方法を調べたを参考にiptablesでポートフォワーディングして50124につなぎます。
ポート周りの設定はiptablesに寄せる方針です。
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# HTTP
-A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 50123
# HTTPS
-A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 50124
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 50123 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 50124 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
- *filterに443と50124ポートのポート開放の設定を
- *natに443ポートをlistenした場合は50124にポートフォワーディングをする設定を
書きます。
(上記内容は80番ポートの設定も一緒に記載しています)
Goのサーバーを起動してみる
root以外のユーザーで起動してみます
go run server.go
ブラウザで https://localhost/login
vagrantとかなら https://{IPアドレス}/login
にアクセスしてみください。
最後に
HTTPSとHTTPをserver.goで同時に動かしたいんだけども方法がわからない・・・・・