Redis配置文件中bind参数

前言

我们都知道,redis 的配置文件中,默认绑定接口是 127.0.0.1,也就是本地回环接口,所以是无法从外网连接 redis 服务的。如果想要让外网也能连接使用服务器上的 redis 服务,可以简单地注释掉 bind 这一行。但对于 bind 参数的作用,网上有很多文章的解释都是误人子弟的。

关于bind

翻看网上的文章,此处多翻译为:

指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求,在生产环境中最好设置该项。

这种解释会搞糊涂初学者,甚至是错误的。查看配置文件 redis.conf,可以看到很详细的注释说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 lookback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1

翻译过来的意思就是:

默认情况下,如果没有指定bind配置指令,则 Redis 监听来自服务器上所有可用网络接口的连接。可以使用bind配置指令来监听一个或多个选定的接口,在bind后拼接一个或多个 IP 地址即可。例如:

1
2
bind 192.168.1.100 10.0.0.1
bind 127.0.0.1 ::1

警告:如果运行 Redis 的计算机直接暴露在互联网上,绑定到所有的接口是很危险的,并会将实例暴露给互联网上的每个人。因此,默认情况下,我们取消注释以下绑定指令,这将强制 Redis 只监听 IPv4 回环接口地址(这意味着 Redis 只接受来自运行它的计算机上的客户端的连接)。

如果你确定希望你的实例能够监听所有的接口,只需要注释下面的这一行即可。

1
bind 127.0.0.1

网络接口

注释说明 bind 的是 network interfaces,即网络接口(网卡)。服务器可以有一个或者多个网络接口。可以使用 ifconfig 查看当前 Linux 服务器上的网络接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ ifconfig
docker0 Link encap:Ethernet HWaddr 3A:F3:20:12:AE:6A
inet addr:192.168.42.1 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:362879 errors:0 dropped:0 overruns:0 frame:0
TX packets:894703 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:28218097 (26.9 MiB) TX bytes:1326305089 (1.2 GiB)
eth0 Link encap:Ethernet HWaddr 00:16:3E:08:18:35
inet addr:10.25.102.37 Bcast:10.25.103.255 Mask:255.255.252.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4958304 errors:0 dropped:0 overruns:0 frame:0
TX packets:2766733 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:534516269 (509.7 MiB) TX bytes:13382719049 (12.4 GiB)
eth1 Link encap:Ethernet HWaddr 00:16:3E:08:13:6B
inet addr:120.76.207.187 Bcast:120.76.207.255 Mask:255.255.252.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13183600 errors:0 dropped:0 overruns:0 frame:0
TX packets:14070363 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:6460933699 (6.0 GiB) TX bytes:8462002985 (7.8 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:156288093 errors:0 dropped:0 overruns:0 frame:0
TX packets:156288093 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:19039024606 (17.7 GiB) TX bytes:19039024606 (17.7 GiB)
veth802443e Link encap:Ethernet HWaddr 56:E8:12:D0:88:96
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:120 errors:0 dropped:0 overruns:0 frame:0
TX packets:162 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:44625 (43.5 KiB) TX bytes:18533 (18.0 KiB)

我的服务器是阿里云的ECS,当前有5个网络接口。

网络接口 说明
docker0 安装 docker 时自动创建的网桥
eth0 阿里云内网接口
eth1 阿里云公网接口
lo 本地回环接口
veth88f3e3c 运行 docker 容器创建的 veth pair 的一端

所以,如果要让公网可以连接该服务器上的 redis 服务,除了直接注释掉 bind 这一行来绑定到所有的网络接口之外,更正确的做法应该是不注释,再绑定多 eth1 这个公网接口,地址是 120.76.207.187。

1
bind 127.0.0.1 120.76.207.187

然后重启下 redis 服务即可,这样配置,Redis 就只监听 IPv4 的本地回环接口和公网接口。

连接Docker容器中的Redis

如果在 docker 容器里运行 redis 服务,可以在 run 的时候使用 -p 端口映射,比如:

1
$ docker run -ti -p 6380:6379 centos:7 /bin/bash

然后到容器里,查看网络接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:2A:03
inet addr:192.168.42.3 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:162 errors:0 dropped:0 overruns:0 frame:0
TX packets:120 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:18533 (18.0 KiB) TX bytes:44625 (43.5 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

可以发现只有两个网络接口。

  • eth0 实际上是 veth pair 的一端,另一端(veth88f3e3c)连在宿主机的 docker0 网桥上。
  • lo 就是容器里的本地回环地址。

接下来修改配置文件 redis.conf,添加绑定 eth0 接口即可,地址为 192.168.42.3。

1
bind 127.0.0.1 192.168.42.3

配置完成后,在外网就可以通过服务器的公网IP 120.76.207.187 和 6380 端口,映射到容器内的 6379 端口连接 redis。

后话

有不少人会误以为 bind 绑定的 IP 应该是请求来源的 IP。其实不然,绑定的是 redis 服务器本身接受请求的网络接口的 IP 地址。

说到网络接口,就不得不说 Docker 的四种网络方式,之后再整理一篇文章来总结。

  • 本文作者: Bingo
  • 本文链接: https://blog.bingo.ren/62.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!