😀

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

2022/11/28に公開

動的言語しかやったこと無い私ですが、ひょんなことからGoにふれてみることにしました。
まだ、チュートリアルを読んだり、Effective Goを読んでみたりのレベルですが・・・

環境

  • CentOS6.7
    • Go 1.5.2

参考にしたサイト

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

証明書無いと動かないのでオレオレ証明書を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で起動するようにしています

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)
	}
}

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

<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で同時に動かしたいんだけども方法がわからない・・・・・

Discussion