设为首页 收藏本站
查看: 1195|回复: 0

[经验分享] MongoDB数据库安全解决方案

[复制链接]

尚未签到

发表于 2015-11-11 10:28:01 | 显示全部楼层 |阅读模式
本文讨论MonDB数据库安全内容,安全加固包括操作操作系统级别和数据库级别的安全,安全加固的原则是尽量安全,但是不能影响性能。
MonDB集群拓扑如下:
DSC0000.png



1 集群拓扑

拓扑说明:

1.  上图拓扑包括三个副本集,分别构成三个分片,各副本集端口分别为100001000110002

2.  三台服务器上各包括一个配置服务器,端口均为20000

3.  三台服务器上都有一个mongos进程,端口号均为30000

4.  客户端可以访问三个mongos进程,但是不能单独访问分片


安全加固包含如下内容:

1.  启动数据库实例时指定端口,禁用HTTP,指定mongosmongod的监听IP

2.  用操作系统或者硬件防火墙阻止未知主机对数据库各种组件的访问

3. 不要让数据库运行在公用网络上,应该单独设计一个网段

4.  进行安全认证

5.   账户权限最小化

6.   Linux自身安全


1 启动时指定安全选项

1.1 指定端口

如果不指定端口,普通实例启动后使用27017端口,带有—shardsvr选项的实例会使用27018端口,带有—configsvr选项的实例会启用27019端口,各个进程又会启用一个端口比自己大1000http进程,用于通过网页查看状态。使用—nohttpinterface选项可以禁止http进程。


1.2 使用--bind_ip选项

这个选项可以限制监听接口,在服务器多接口情况下适用。

综上所述,可以按照下列命令启动实例
54上的配置服务器为例:
[iyunv@54 ~]# numactl --interleave=all  mongod --dbpath /mongodb/scheme2/config/data \

--configsvr --port 20000 --logpath /mongodb/scheme2/config/logs/config.log \

--fork --directoryperdb --nohttpinterface \

--bind_ip=127.0.0.1,192.168.69.54
集群中所有mongsmongod都应该按照上面选项启动。


2 操作系统防火墙配置

本例,三台机器之间的1000010001100002200000300000端口是相互信任的,客户端也应该可以访问mongos30000端口。
假设客户端运营平台ip192.168.69.46,为实现需求,配置规则如下:
192.168.69.54为例,修改防火墙配置文件:
/etc/sysconfig/iptables
# Manual customization of this file is not recommended.

*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 -s 192.168.69.54,192.168.69.55,192.168.69.56 -m state --state NEW -m tcp -p tcp --dport 10000 -j ACCEPT

-A INPUT -s 192.168.69.54,192.168.69.55,192.168.69.56 -m state --state NEW -m tcp -p tcp --dport 10001 -j ACCEPT

-A INPUT -s 192.168.69.54,192.168.69.55,192.168.69.56 -m state --state NEW -m tcp -p tcp --dport 10002 -j ACCEPT

-A INPUT -s 192.168.69.54,192.168.69.55,192.168.69.56 -m state --state NEW -m tcp -p tcp --dport 20000 -j ACCEPT

-A INPUT -s 192.168.69.46,192.168.69.54,192.168.69.55,192.168.69.56 -m state --state NEW -m tcp -p tcp --dport 30000 -j ACCEPT

-A INPUT -j REJECT --reject-with icmp-host-prohibited

-A FORWARD -j REJECT --reject-with icmp-host-prohibited

COMMIT
修改完成后启动防火墙:
[iyunv@56 ~]# service iptables save

[iyunv@56 ~]# service  iptables start

[iyunv@56 ~]# service ip6tables start


3 认证与授权功能

3.1 单实例认证

启动时启用--auth选项
1. 启动实例:
numactl --interleave=all  mongod   --port 40000 \

--dbpath=/mongodb/scheme2/sin/data \

--logpath=/mongodb/scheme2/sin/logs/sin.log --logappend --fork --directoryperdb \

--bind_ip=127.0.0.1,192.168.69.54 --nohttpinterface \

--auth
2. 使用本地例外方式登录数据库
[iyunv@54 ~]# mongo --port 40000

MongoDB shell version: 2.4.4

connecting to: 127.0.0.1:40000/test

>



注意:本地例外方式类似oracle操作系统认证方式,登录后具备所有权限。在没有建立帐号时,需要使用本地例外方式登录。可以用下面选项关闭本地例外认证方式:
--setParameter enableLocalhostAuthBypass=0



3. 创建系统管理员用户(角色为userAdminAnyDatabase或者userAdmin
默认条件下,超级管理员只能用于帐号管理,不能进行其他数据库操作,可以通过自己给自己授权实现。生产环境中的管理员,如果某个帐号包含了角色userAdminAnyDatabase或者userAdmin,就应该仅仅用于帐号和角色管理,不应该再授予别的角色了。
我们首先就要建立一个超级管理员,然后再用超级管理员建立其他帐号:
1) 建立超级管理员帐号:
> db= db.getSiblingDB('admin')

> db.addUser({ user: "superman",

pwd: "talent",

roles: [ "userAdminAnyDatabase"] } )      --创建第一个账户时候,指定角色是超级管理员

{

        "user" : "superman",

        "pwd" : "a6de521abefc2fed4f5876855a3484f5",

        "roles" : [

                "userAdminAnyDatabase"

        ],

        "_id" : ObjectId("51fa3108a0e7aeded08baf35")

}
2)为帐号启用admin数据库认证,这样他就可以操作admin数据库了。
> db.auth("superman","talent")

> db.system.users.find().pretty();

{

        "_id" : ObjectId("51fa3108a0e7aeded08baf35"),

        "user" : "test",

        "pwd" : "a6de521abefc2fed4f5876855a3484f5",

        "roles" : [

                "userAdminAnyDatabase"

        ]

}

>
4)使用用刚才的超级帐号登录数据库(admin)
[iyunv@54 ~]#  mongo localhost:40000/admin -u superman -p superman      

现在,我们就可以为其他数据库添加用户了:

> use test

switched to db test

> db.addUser("supermantest","supermantest")

{

        "user" : "supermantest",

        "readOnly" : false,

        "pwd" : "489151cf34eaf7473ff69a18acb36a49",

        "_id" : ObjectId("51fa618b49713cce4ee1d94b")

}

授予这个用户的权限:(必须要,否则无法进行读写操作)

> db.auth("supermantest","supermantest")

1

5)现在可以用新用户登录并且操作test数据库了


4.关闭本地例外登录方式

一旦拥有了超级管理员,就可以考虑关闭本地例外方式登录了

方法如下:

重启数据库,启动时候加上--setParameter enableLocalhostAuthBypass=0即可,这样登录的话就必须要用账户认证了

5.删除用户

删除用户要针对某个数据库进行删除

> use test

switched to db test

> db.removeUser("superman11111")

6.修改用户密码

普通用户只能修改自己的密码,userAdmin角色帐号可以修改其他用户密码

例如:

[iyunv@55 ~]# mongo 192.168.69.54:40000/admin -u superman -p superman

MongoDB shell version: 2.4.4

connecting to: 192.168.69.54:40000/admin

> use test

switched to db test

> db.changeUserPassword("supermantest","talent")

>

3.2 副本集成员认证


副本集之间的认证可以通过keyFile实现
KeyFile文件必须满足条件:
(1)至少6个字符,小于1024字节
(2)认证时候不考虑文件中空白字符
(3)连接到副本集的成员和mongos进成的keyfile文件内容必须一样
(4)必须是base64编码,但是不能有等号
(5)文件权限必须是x00,也就是说,不能分配任何权限给group成员和other成员
以副本集sh0为例:
1.生成keyFile文件:
54上执行:
[iyunv@54 ~]# openssl rand -base64 100 > /mongodb/scheme2/keyfile0 --文件内容采base64编码,一共100个字符
2.修改文件权限:
[iyunv@54 ~]# chmod600 /mongodb/scheme2/keyfile0

把生成的文件拷贝到副本集剩余各台机器上,存放的目录可以不一样,注意权限。
3.三台机器启动时指定--keyFile选项
numactl --interleave=all mongod  --replSet sh0 --port 10000 \

--dbpath=/mongodb/scheme2/sh0/data --logpath=/mongodb/scheme2/sh0/logs/sh0.log \

--logappend --fork --directoryperdb --bind_ip=127.0.0.1,192.168.69.54 --nohttpinterface \

--keyFile=/mongodb/scheme2/keyfile0
这样,没有这个文件的机器就无法加入副本集,Sh1sh2副本集的操作类似。
开启了keyFile,隐含就开启了auth,这个时候连接副本集就需要进行认证了,否则只能通过本地例外方式操作数据库。


3.3 副本集+分片环境下的认证


结合上面的两种环境的认证方式,可以实现副本集+分片环境中安全认证,需要注意以下几点

1.在分片集群环境中,副本集内成员之间需要用keyFile认证,mongos与配置服务器,副本集之间也要keyFile认证,集群所有mongodmongos实例使用内容相同的keyFile文件。
2.进行初始化,修改副本集时,都从本地例外登录进行操作
3.由于启用了认证,需要建立一个管理员帐号,才能从远程登录。建立管理员帐户,利用管理员账户从远程登录后,需要建立一个可以操作某个数据库的用户,客户端就用这个用户访问数据库。
4.分片集群中的管理员帐号需要具备配置服务器中adminconfig数据库的读写权限,才能进行分片相关操作
5.集群中每个分片有自己的admin数据库,存储了集群的各自的证书和访问权限。如果需要单独远程登录分片,可以按照3.2的办法建立用户
相关操作如下:
1.启动集群中的配置服务器,路由进程和副本集,每个进程都要指定KeyFile文件,而且每个进程的keyfile内容相同,详细操作见3.2
2.初始化副本集。
3. 连接mongos,为集群建立管理员帐号和普通帐号,步骤如下;
(1)建立管理员帐号
管理员需要具备对集群中配置服务器的读写权限,这些权限包括:
建立新的普通管理员,用于客户端连接集群中的数据库;
分片相关权限,例如查看分片状态,启用分片,设置片键等操纵。
首先用本地例外方式登录,建立管理员帐号:
[iyunv@54 ~]# mongo --port 30000

mongos> use admin

db.addUser( { user: "superman",

pwd: "superman",

roles: [ "clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase","readWriteAnyDatabase" ] } )



mongos> db.auth("superman","superman")



mongos> use config

switched to db config

mongos> db.addUser( { user: "superman",

  pwd: "superman",

  roles: [ "clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase","readWriteAnyDatabase" ] } )
mongos> db.auth("superman","superman")


(2)
用上面建立的管理员帐号登录mongos进程,对数据库(比如test)启用分片,设置集合片键。


3)用管理员账户登录,建立新账户,让他可以读写数据库test
[iyunv@54 ~]# mongolocalhost:30000/admin -u superman -p superman

mongos> use test

switched to db test

mongos> db.addUser("test","test")

{

        "user" : "test",

        "readOnly" : false,

        "pwd" : "a6de521abefc2fed4f5876855a3484f5",

        "_id" : ObjectId("51fb5d4ecaa5917203f37f63")

}

mongos> db.auth("test","test")

1
4)用新帐号test登录,操作数据库test
[iyunv@54 ~]# mongo localhost:30000/test -u test -p test            

MongoDB shell version: 2.4.4

connecting to: localhost:30000/test

> for(var i = 1; i < 100000; i&#43;&#43; ) db.test.insert( { x:i, C_ID:i } );



说明:为分片集群启用认证后,本地例外方式登录由于只具备admin数据库读写权限,无法进行分片操作。对本例来讲,添加分片,查看分片状态等操作都需要用superman帐号登录才行。执行数据库test操作用test帐号,这个帐号就是提供给客户端的帐号。




4 Linux自身安全加固

Linux自身安全加固包含一下几个方面:
1.         网络安全
2.         服务安全
3.         文件系统安全
4.         账户安全
5.         帐号资源限制

4.1 网络安全

网络安全包括如下几个部分:


4.1.1 关闭不必要的端口


关闭端口可以通过linux的防火墙来实现,本集群系统中各台机器使用的mongodb端口要相互开放,22端口要开放给管理区域。第二章已经说明了其用法


4.1.2 不设置默认路由


内网运行的linux都不应该设置默认路由,只要管理区域和web服务器可以访问数据库即可
以本集群环境为例
不添加网关,只要机器与73网段互通,当前路由如下:
[iyunv@54 ~]# route

Kernel IP routing table

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

192.168.69.0    *               255.255.255.0   U     0      0        0 eth1

link-local      *               255.255.0.0     U     1002   0        0 eth1

default         192.168.69.1    0.0.0.0         UG    0      0        0 eth1
现在要做的是,删掉默认路由,添加一条到192.168.73.0网段的静态路由即可
[iyunv@54 ~]# route add -net 192.168.73.0/24 gw 192.168.69.1 dev eth1

[iyunv@54 ~]# route del default
如果要使重启继续生效,执行如下操作:
1)打开网卡配置文件:/etc/sysconfig/network-scripts/ifcfg-eth1,注释掉网关部分(网关配置有时候可能会写到/etc/sysconfig/network

2)把上面添加静态路由的语句写入开机启动文件/etc/rc.local


4.1.3禁用ipv6

如果环境不需要ipv6,就把它禁掉
(1)           编辑文件/etc/sysconfig/network,加入如下两行

NETWORKING_IPV6=no

IPV6INIT=no

(2)           修改ipv6模块配置文件,把ipv6模块禁用掉:

echo  &quot;options ipv6 disabled=1&quot; > /etc/modprobe.d/ipv6.conf

或者用 echo  &quot;install ipv6 /bin/true&quot; > /etc/modprobe.d/ipv6.conf

(3)           重启系统

4.2 服务安全

服务安全包括关闭不必要的和服务,优化ssh服务,以非root帐号运行数据库。


4.2.1 关闭不必要的服务

安装完成后,如果安装了桌面,linux将会以运行级5运行。如果不需要用桌面,不建议安装,在安装系统时候,选择基础安装,然后选择部分开发包和system-config界面即可。重启后,linux将会以运行级别3运行。可以查看/etc/inittab文件确认
找到id:3:initdefault:部分,确认红色数字是3
进入命令行,使用如下命令关闭不必要的服务:
[mongo_46 ~]# export LANG=&quot;zh_CN.UTF-8&quot;
[mongo_46 ~]# ntsysv      ---打开系统服务设置窗口


只需要保留如下服务:
Cpupeed,crond,iptables,network, irqbalance,ssh, rsyslog,udev-post, messagebus, sysstat


4.2.2 SSH服务修改

1)默认ssh服务是22端口,可以修改:
打开/etc/ssh/sshd_config,找到#Port 22部分,去除#,修改为Port28,同时设置28为防火墙信任端口。

2)禁用root帐号sshd登录:
找到ssh服务配置文件/etc/ssh/sshd_config,找到#PermitRootLoginyes部分,修改为PermitRootLogin no,重启ssh服务。接下来用mongod登录登录然后切换到root


4.2.3 以非root帐号运行数据库

不要以root账户运行软件,因为这样会造成软件运行权限过大,威胁系统自身安全。同时,也不方便对帐号资源进行限制。
1. 配置mongod用户
[iyunv@54 mongodb]# groupadd mongod

[iyunv@54 mongodb]# groupadd mongod

[iyunv@54 mongodb]# useradd -d /mongodb -g mongod mongod

[iyunv@54 mongodb]# chown -R mongod.mongod /mongodb

[iyunv@54 mongodb]# su - mongod

-bash-4.1$ vi .bash_profile

export PATH

# .bash_profile



# Get the aliases and functions

if [ -f ~/.bashrc ]; then

        . ~/.bashrc

fi



# User specific environment and startup programs



PATH=$PATH:$HOME/bin



export PATH=$PATH:/mongodb/bin

2.  切换到mongod账户,进行数据库建立和集群相关操作。


4.3 文件系统安全

Linux默认文件权限为644,文件夹权限是755,无特殊需要不要修改。在使用mondb时候,如果遇到权限问题,不要把权限设置为777,一般设置为700,保证账户mongod具备一定权限即可。如果要求每个新建立的帐号权限都是600,可以用下列命令实现(集群中keyFile文件权限就必须是x00)
oracle[~]$umask  007

4.4 帐号安全
安装linux时,一般会要求设置一个帐号,只有新建立的帐号和root帐号具备登录资&#26684;,不要使用系统保留帐号登录系统。在mongodb集群环境中,每台操作系统都应该只允许mongodroot启动shell
帐号口令应该满足一定复杂度:包含大小写字母,数字和特殊字符。
为了更安全,可以不用帐号密码认证,而是启用ssh公钥和私钥认证,以securecrt配置方法为例:

1. shd服务设置:
打开配置文件/etc/ssh/sshd_config,修改已有的配置,确保有如下几行
StrictModes no
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      /root/.ssh/authorized_keys
PermitEmptyPasswords yes
PasswordAuthentication no
  
2.SecureCRT设置
会话属性-> Authentiation -> Public Key -> Properties ->Create Identity File ->RSA(选择RSA加密算法) -> Set Passphrase (设置密码,保护公钥)-> Done

完成时会在指定目录(一般是C:\Users\’username’\Documents)生成两个文件,默认名称为:私钥Identity和公钥Identity.pub

3.将公钥Identity.pub传到Linux服务器的/root/.ssh/,将SSH2兼容&#26684;式的公钥转换成为Redhat兼容&#26684;式。
[~/.ssh]#ssh-keygen -i -f  /root/.ssh/Identity.pub  >  /root/.ssh/authorized_keys
[~/.ssh]#chmod 600  /root/.ssh/authorized_keys

4. 使用SecureCRT登录服务器首先设置登录模式为PublicKey,并选择刚刚创建的公钥文件Identity.pub
重启Linux服务器的sshd服务。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-137802-1-1.html 上篇帖子: mongoDB数据库的修复 下篇帖子: node.js mongodb数据库驱动性能测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表