LoginSignup
8
2

More than 3 years have passed since last update.

Goのredigoを使って堅牢なRedisとPub/Sub通信のPublishを行ってみる

Last updated at Posted at 2020-12-18

はじめに

この記事はand factory Advent Calendar 202018日目の記事です。
昨日は @ichi-nakashimaさんの【React Hooks】Component から stateを伴ったロジックを切り出す技術たちでした。

RedisにはPub/Sub機能がある

Redisと言えばKVS(Key-Value Store)として使われるのが一般的と思いますが、Pub/Sub機能も備わっているので、こいつを使ってGoとやり取りをしてみたいと思います。

RedisのPub/Sub機能とは

それぞれPublish(発行)Subscrib(購読)という意味で、RedisではあるChannelを作成して、
そのChannelに対してメッセージをPublish(発行)したりSubscrib(購読)したりする(=メッセージの発信・受信みたいな)ことができる機能を指します。

今回は堅牢なRedisを立ててそいつに対してGoからPublishを行ってみます。

Redisサーバーを立てる

一応自分で試した環境はVagrant+VM上のCentOS7にRedisをインストールしました。
以下はインストール時の一連(EPELのリポジトリ追加→Redisインストール)のログ

まずはEPELのリポジトリの追加
(※EPELについては CentOSなどで使う、EPELってなんだ? - Qiita などを参照してください。)

[vagrant@localhost ~]$ sudo yum install epel-release
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.tsukuba.wide.ad.jp
 * extras: ftp.tsukuba.wide.ad.jp
 * updates: download.nus.edu.sg
Resolving Dependencies
--> Running transaction check
---> Package epel-release.noarch 0:7-11 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===================================================================================================================================================================
 Package                                     Arch                                  Version                             Repository                             Size
===================================================================================================================================================================
Installing:
 epel-release                                noarch                                7-11                                extras                                 15 k

Transaction Summary
===================================================================================================================================================================
Install  1 Package

Total download size: 15 k
Installed size: 24 k
Is this ok [y/d/N]: y
Downloading packages:
epel-release-7-11.noarch.rpm                                                                                                                |  15 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : epel-release-7-11.noarch                                                                                                                        1/1
  Verifying  : epel-release-7-11.noarch                                                                                                                        1/1

Installed:
  epel-release.noarch 0:7-11

Complete!

次にRedisのインストール

[vagrant@localhost ~]$ sudo yum install redis -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink                                                                                                                        | 6.4 kB  00:00:00
 * base: ftp.tsukuba.wide.ad.jp
 * epel: download.nus.edu.sg
 * extras: ftp.tsukuba.wide.ad.jp
 * updates: download.nus.edu.sg
epel                                                                                                                                        | 4.7 kB  00:00:00
(1/3): epel/x86_64/group_gz                                                                                                                 |  95 kB  00:00:01
(2/3): epel/x86_64/updateinfo                                                                                                               | 1.0 MB  00:00:02
(3/3): epel/x86_64/primary_db                                                                                                               | 6.8 MB  00:00:01
Resolving Dependencies
--> Running transaction check
---> Package redis.x86_64 0:3.2.12-2.el7 will be installed
--> Processing Dependency: libjemalloc.so.1()(64bit) for package: redis-3.2.12-2.el7.x86_64
--> Running transaction check
---> Package jemalloc.x86_64 0:3.6.0-1.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===================================================================================================================================================================
 Package                                Arch                                 Version                                      Repository                          Size
===================================================================================================================================================================
Installing:
 redis                                  x86_64                               3.2.12-2.el7                                 epel                               544 k
Installing for dependencies:
 jemalloc                               x86_64                               3.6.0-1.el7                                  epel                               105 k

Transaction Summary
===================================================================================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 648 k
Installed size: 1.7 M
Downloading packages:
warning: /var/cache/yum/x86_64/7/epel/packages/jemalloc-3.6.0-1.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY0 B/s |    0 B  --:--:-- ETA
Public key for jemalloc-3.6.0-1.el7.x86_64.rpm is not installed
(1/2): jemalloc-3.6.0-1.el7.x86_64.rpm                                                                                                      | 105 kB  00:00:02

(2/2): redis-3.2.12-2.el7.x86_64.rpm                                                                                                        | 544 kB  00:00:02
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                              293 kB/s | 648 kB  00:00:02
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Importing GPG key 0x352C64E5:
 Userid     : "Fedora EPEL (7) <epel@fedoraproject.org>"
 Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5
 Package    : epel-release-7-11.noarch (@extras)
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : jemalloc-3.6.0-1.el7.x86_64                                                                                                                     1/2
  Installing : redis-3.2.12-2.el7.x86_64                                                                                                                       2/2
  Verifying  : redis-3.2.12-2.el7.x86_64                                                                                                                       1/2
  Verifying  : jemalloc-3.6.0-1.el7.x86_64                                                                                                                     2/2

Installed:
  redis.x86_64 0:3.2.12-2.el7

Dependency Installed:
  jemalloc.x86_64 0:3.6.0-1.el7

Complete!

Redisのインストールが完了したので立ち上げる

[vagrant@localhost ~]$ sudo systemctl start redis.service

Redisの自動起動を有効にする

[vagrant@localhost ~]$ sudo systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.

最後にRedisの状態を確認する

[vagrant@localhost ~]$ sudo systemctl status redis.service
● redis.service - Redis persistent key-value database
   Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/redis.service.d
           └─limit.conf
   Active: active (running) since Mon 2020-07-13 09:43:21 UTC; 31s ago
 Main PID: 22002 (redis-server)
   CGroup: /system.slice/redis.service
           └─22002 /usr/bin/redis-server 127.0.0.1:6379

Jul 13 09:43:21 localhost.localdomain systemd[1]: Starting Redis persistent key-value database...
Jul 13 09:43:21 localhost.localdomain systemd[1]: Started Redis persistent key-value database.

念のためredis-cliコマンドでpingを行い、PONGと返ってくるか確認する。
※このpingコマンドは疎通確認によく使用されるコマンドです。

[vagrant@localhost ~]$ redis-cli ping
PONG

あとは/etc/redis.confを編集してIPアドレスなどを設定すればRedisのインストールは完了

[vagrant@localhost ~]$ sudo vi /etc/redis.conf

Redisを堅牢にする(パスワードの設定)

[vagrant@localhost ~]$ echo "secretkey" | sha256sum
92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a -
[vagrant@localhost ~]$ sudo vi /etc/redis.conf

SECURITYの項目があるので、その下にrequirepassを追加し、パスワードを記述する。

/etc/redis.conf

################################## SECURITY ###################################

# Require clients to issue AUTH <PASSWORD> before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
requirepass 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a

(※ここではsha256sumを使って生成したハッシュ値をパスワードとして設定していますが、ある程度の長さがあればいいと思います。)

/etc/redis.conf編集後にRedisを再起動し、redis-cliから先ずはパスワードなしの状態でコマンドを実行する。

[vagrant@localhost ~]$ sudo systemctl restart redis.service
[vagrant@localhost ~]$ redis-cli
127.0.0.1:6379> set key 10
(error) NOAUTH Authentication required.

上記のように認証エラーがでることを確認。
次にauthコマンドを書き、先ほど設定したパスワードを入れて実行する。

127.0.0.1:6379> auth 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a
OK

OKが出れば認証された状態なので、コマンドを実行すれば以下のようにふつうに動くようになる。

127.0.0.1:6379> set key 10
OK
127.0.0.1:6379> get key
"10"
127.0.0.1:6379> quit

Goのサンプルコード

サンプルコードはパスワードを設定したRedisにパブリッシュする処理を書いています。(※パスワード設定は必須ではないです。念のため)

package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

// RedisPublish : コマンドをRedisへパブリッシュする
func RedisPublish(message string) (int, error) {
    conn, redisAuthPass, err := ConnectionRedis()
    if err != nil {
        fmt.Println(err)
        return 0, err
    }
    defer conn.Close()

    // パス認証
    if redisAuthPass != "" {
        _, err = conn.Do("AUTH", redisAuthPass)
        if err != nil {
            fmt.Println(err)
            return 0, err
        }
    }

    // パブリッシュ
    res, err := redis.Int(conn.Do("PUBLISH", "test_channel", message))
    if err != nil {
        fmt.Println(err)
        return 0, err
    }

    return res, err
}

// ConnectionRedis : Redisと接続し接続情報とAuthパスを返す
func ConnectionRedis() (redis.Conn, string, error) {
    // RedisのAUTHパス
    AuthPass := "92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a"            
    // RedisのIPアドレス
    RedisIPAddress := "192.168.33.100"
    // Redisのポート番号
    RedisPort := "6379"

    // 接続
    conn, err := redis.Dial("tcp", RedisIPAddress+":"+RedisPort)
    if err != nil {
        fmt.Println(err)
        return nil, "", err
    }

    return conn, AuthPass, err
}

実際にはAUTHパスとかは環境によって変わると思うので、ソースに書かずに.envとかに記述して読み込むのがいいと思います。
参考:【Go】.envファイルをGolangでも使用するためのライブラリ「godotenv」 - Qiita

Redisをさらに堅牢にする

個人的にはRedisに接続する際のAuthパスだけでもいいと思うんですが念には念を入れて強化する場合は以下のことが出来ます。

ポート番号の変更

Redisのデフォルトポート番号は6379番ですが、これを変更することで多少なりともセキュリティが向上します。

/etc/redis.conf
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
# port 6379
port 6597

変更後はRedisの再起動すること。

重要なコマンドの変更

例えばCONFIGSHUTDOWNFLUSHDBコマンドなど、実行されるとマズいコマンドをほかの文字列に置き換えることが出来ます。
代わりのコマンド名を以下のredis.confに追記して再起動をすることで適用されます。

/etc/redis.conf
# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG ""
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to slaves may cause problems.
rename-command CONFIG configconfig
rename-command FLUSHDB SF_FLUSHDB
rename-command SHUTDOWN RENAME_SD

以下コマンドがかわっているか確認の様子

[vagrant@localhost ~]$ sudo systemctl restart redis.service
[vagrant@localhost ~]$ redis-cli
127.0.0.1:6379> auth 92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a // 上で設定したパス
OK
127.0.0.1:6379> config get requirepass
(error) ERR unknown command 'config' // configというコマンドは無い(上で変更したため)
127.0.0.1:6379> configconfig get requirepass
1) "requirepass"
2) "92d4e0a2ad853e81e6d4bf147618aae5a06f201e6e72a67794a542409c9d125a"
127.0.0.1:6379> exit

Redisデータディレクトリの権限変更

RedisユーザーとRedisグループのみがアクセスできるように770に変更する。

[vagrant@localhost ~]$ ls -l /var/lib | grep redis
drwxr-x---. 2 redis   redis     22 Jul 13 13:31 redis

[vagrant@localhost ~]$ sudo chmod 770 /var/lib/redis

[vagrant@localhost ~]$ ls -l /var/lib | grep redis
drwxrwx---. 2 redis   redis     22 Jul 13 13:31 redis

おわり

  • なんか走り書きしたら雑なまとめになってしまった感がある・・・
  • ちなみにSubscribは今度時間あれば書くかもしれません・・・(予定は未定です)
  • あとまだRedisは構成ファイルの権限変更したりなどで強固にできますがここでは割愛します(DigitalOceanさんの参考記事をどうぞ)

参考URL

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2