net/httpでポート443のHTTPSサーバーを立ち上げるまで


動的言語しかやったこと無い私ですが、ひょんなことからGoにふれてみることにしました。
まだ、チュートリアルを読んだり、[Effective Go](http://go.shibu.jp/effective_go.html)を読んでみたりのレベルですが・・・

## 環境

* CentOS6.7
	* Go 1.5.2

## 参考にしたサイト

* [golang の HTTPS サーバで StartSSL の無料 SSL 証明書を使うには
](http://bl.oov.ch/2011/02/golang-https-startssl-ssl.html)
* [GoのHTTPサーバーを80番や443番ポートでListenする方法を調べた](http://matope.hatenablog.com/entry/2014/09/28/031155)
* [オレオレ証明書をopensslで作る（詳細版）](http://d.hatena.ne.jp/ozuma/20130511/1368284304)
* [Build web application with Golang](https://www.gitbook.com/book/astaxie/build-web-application-with-golang/details)


## まずはオレオレ証明書を作ってみる

証明書無いと動かないので[オレオレ証明書をopensslで作る（詳細版）](http://d.hatena.ne.jp/ozuma/20130511/1368284304)を参考に証明書を作成


```shell
$ 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で起動するようにしています

```go:server.go
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)
	}
}
```

以下ログインフォームのテンプレート

```login.gtpl
<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する方法を調べた](http://matope.hatenablog.com/entry/2014/09/28/031155)を参考にiptablesでポートフォワーディングして50124につなぎます。

ポート周りの設定はiptablesに寄せる方針です。


```/etc/sysconfig/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以外のユーザーで起動してみます

```shell
go run server.go
```


ブラウザで ``` https://localhost/login ``` vagrantとかなら ``` https://{IPアドレス}/login ``` にアクセスしてみください。



## 最後に

HTTPSとHTTPをserver.goで同時に動かしたいんだけども方法がわからない・・・・・