GitLab 接入 OpenLDAP和AD域

今天调试GitLab接入AD域控,找了很多资料才解决了问题,在此处做记录。

GitLab有自己的用户机制,但其也兼容ldap的用户验证机制(本质上OpenLDAP和AD域控都是基于LDAP机制),由于公司内部的统一账户机制正在调整,故需要将GitLab进行配置,试验下来社区版的GitLab经过修改配置文件后可以使用OpenLDAP和微软AD域控作为其用户机制。

版本:gitlab 社区版 9.3.4(汉化)

gitlab目录:/etc/gitlab

gitlab配置文件:/etc/gitlab/gitlab.rb(社区版初始该文件内容为空)

一、接入openldap

1.1 修改配置文件gitlab.rb

在gitlab.rb文件中添加下面配置,其中:

  1. host,是搭建的openldap的ip,根据实际情况修改;

  2. uid,可以配置cn,也可以配置uid,都能识别(具体为什么没深入研究);

  3. bind_dn,openldap的管理员账号,根据实际情况修改;

  4. password,openldap的管理员,根据实际情况修改;

  5. active_directory,似乎是针对连接是否是ad域控的标示,因为这部分是openldap的配置,故为false;

  6. allow_username_or_email_login,用户登录是否用户名和邮箱都可以,方便用户故配置true;

  7. base,用户列表所在的目录,因为新增的用户都在openldap的People下,故这么配置,根据实际情况修改;

# 指明服务的地址
external_url = 'http://localhost'

# 开启ldap
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' ###! **remember to close this block with 'EOS' below**
main: # 'main' is the GitLab 'provider ID' of this LDAP server
    label: 'LDAP'
    host: '192.168.6.4'
    port: 389
    uid: 'uid'
    method: 'plain' # "tls" or "ssl" or "plain"
    bind_dn: 'cn=Manager,dc=abc,dc=cn'
    password: '123456' 
    active_directory: false
    allow_username_or_email_login: true
    block_auto_created_users: false
    base: 'ou=People,dc=abc,dc=cn'
    user_filter: ''
EOS

1.2 重新加载新配置

# gitlab-ctl reconfigure

运行后最后一行为“gitlab Reconfigured!”才说明是加载新配置成功,否则就是根据报错信息找错误。

1.3 查看是否能正常获取用户列表

# gitlab-rake gitlab:ldap:check

正常连接的情况下执行之后能看到用户的列表

1.4 重启gitlab

# gitlab-ctl restart

未分类

重启成功后,gitlab的界面就会变成下面这样。

未分类

openldap的用户通过“LDAP”页进入,管理员root通过“标准”页进入。

二、接入AD

2.1 修改配置文件gitlab.rb

在gitlab.rb文件中添加下面配置,其中:

  1. host,是搭建的微软域服务器的ip,根据实际情况修改;

  2. uid,必须配sAMAccountName才能识别;

  3. bind_dn,域服务器的管理员账号,根据实际情况修改;

  4. password,域服务器的管理员,根据实际情况修改;

  5. active_directory,似乎是针对连接是否是ad域控的标示,因为这部分是域服务器的配置,故为true;

  6. allow_username_or_email_login,用户登录是否用户名和邮箱都可以,方便用户故配置true;

  7. base,用户列表所在的目录,因为新增的用户都在People下(试验了用户放在User时gitlab检测不到用户,故新建了一个目录People,并将新建的用户移入了该目录下),故这么配置,根据实际情况修改;

external_url = 'http://localhost'

gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' ###! **remember to close this block with 'EOS' below**
main: # 'main' is the GitLab 'provider ID' of this LDAP server
  label: 'LDAP'
  host: '192.168.6.1'
  port: 389
  uid: 'sAMAccountName'
  method: 'plain' # "tls" or "ssl" or "plain"
  bind_dn: 'cn=Administrator,cn=users,dc=myad,dc=cn'
  password: '123456'
  active_directory: true
  allow_username_or_email_login: true
  block_auto_created_users: false
  base: 'ou=People,dc=myad,dc=cn'
  user_filter: ''
EOS 

2.2 重新加载新配置

# gitlab-ctl reconfigure

运行后最后一行为“gitlab Reconfigured!”才说明是加载新配置成功,否则就是根据报错信息找错误。

2.3 查看是否能正常获取用户列表

# gitlab-rake gitlab:ldap:check

正常连接的情况下执行之后能看到用户的列表

2.4 重启gitlab

# gitlab-ctl restart

未分类

重启成功后,gitlab的界面就会变成下面这样。

未分类

openldap的用户通过“LDAP”页进入,管理员root通过“标准”页进入。

2.5 确认该用户不处于特殊状态

  1. 不处于“禁用账户”的状态;

  2. 不处于“需要首次登录修改密码”的状态;

(处于上面任意一种状态的账户在登录gitlab时都会报“Cloud not authenticate you from Ldapmain because “Invalid creadentials”.”)

搭建 gitlab 服务器

apt-get install gitlab-ce 失败

问题 log: gem devise-two-factor 的依赖关系得不到满足。

Setting up ruby-paranoia (2.1.3-1) ...
Setting up gitlab (8.5.8+dfsg-5) ...
Creating/updating gitlab user account...
adduser: Warning: The home directory `/var/lib/gitlab' does not belong to the user you are currently creating.
Creating runtime directories for gitlab...
Updating file permissions...
Configuring hostname and email...
Registering /etc/gitlab/gitlab.yml via ucf

Creating config file /etc/gitlab/gitlab.yml with new version
Registering /etc/gitlab/gitlab-debian.conf via ucf

Creating config file /etc/gitlab/gitlab-debian.conf with new version

Creating config file /etc/nginx/sites-available/localhost with new version
Reloading nginx configuration...
Create database if not present
psql: FATAL:  database "gitlab_production" does not exist
psql: FATAL:  role "gitlab" does not exist
Create gitlab user with create database privillege...
CREATE ROLE
Make gitlab user owner of gitlab_production database...
ALTER DATABASE
Grant all privileges to gitlab user...
GRANT
Verifying we have all required libraries...
Could not find gem 'devise-two-factor (~> 2.0.0)' in any of the gem sources
listed in your Gemfile or available on this machine.
dpkg: error processing package gitlab (--configure):
 subprocess installed post-installation script returned error exit status 7
Setting up ruby-debug-inspector (0.0.2-1.1build3) ...
Setting up ruby-binding-of-caller (0.7.2+debian1-3) ...
Setting up ruby-bson (1.10.0-2) ...
Setting up ruby-bson-ext (1.10.0-2build5) ...
Setting up ruby-columnize (0.9.0-1) ...
Setting up ruby-byebug (5.0.0-1build3) ...
Setting up ruby2.3-dev:amd64 (2.3.1-2~16.04.2) ...
Setting up ruby-dev:amd64 (1:2.3.0+1) ...
Setting up ruby-ffi (1.9.10debian-1build2) ...
Setting up ruby-jbuilder (2.3.1-1) ...
Setting up ruby-libvirt (0.5.1-3build5) ...
Setting up ruby-rb-inotify (0.9.7-1) ...
Setting up ruby-listen (3.0.3-3) ...
Setting up ruby-msgpack (0.6.2-1build4) ...
Setting up ruby-rabl (0.11.4-2) ...
Setting up ruby-rabl-rails (0.4.1-1) ...
Setting up ruby-sdoc (0.4.1-1) ...
Setting up ruby-spring (1.3.6-2) ...
Setting up ruby-sqlite3 (1.3.11-2build1) ...
Setting up ruby-web-console (2.2.1-2) ...
Processing triggers for libc-bin (2.23-0ubuntu9) ...
Processing triggers for systemd (229-4ubuntu19) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for ufw (0.35-0ubuntu2) ...
Errors were encountered while processing:
 gitlab
E: Sub-process /usr/bin/dpkg returned an error code (1)
netadmin@kmc-b0232:~$

改用官方最新的 deb 包

详见 https://packages.gitlab.com/gitlab/gitlab-ce/install,

  • curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
  • sudo apt-get install gitlab-ce
netadmin@kmc-b0232:~$ curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
Detected operating system as Ubuntu/xenial.
Checking for curl...
Detected curl...
Running apt-get update... done.
Installing apt-transport-https... done.
Installing /etc/apt/sources.list.d/gitlab_gitlab-ce.list...done.
Importing packagecloud gpg key... done.
Running apt-get update... done.

The repository is setup! You can now install packages.
netadmin@kmc-b0232:~$

配置

目前还未配置邮件发送。

nginx

gitlab 默认使用 nginx。安装完后 nginx sites-enabled 有两个,我把 default 直接删了。
然后把另一个的 server_name 改成自己的 ip。修改完记得 sudo service nginx restart。

netadmin@kmc-b0232:/etc/nginx/sites-available$ ls ../sites-enabled/ -al
total 8
drwxr-xr-x 2 root root 4096 12月 13 19:42 .
drwxr-xr-x 6 root root 4096 12月 13 19:40 ..
lrwxrwxrwx 1 root root   36 12月 13 14:23 gitlab -> /etc/nginx/sites-available/localhost
netadmin@kmc-b0232:/etc/nginx/sites-available$ cat gitlab
## GitLab
##
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
##
##################################
##        CONTRIBUTING          ##
##################################
##
## If you change this file in a Merge Request, please also create
## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
##
###################################
##         configuration         ##
###################################
##
## See installation.md#using-https for additional HTTPS configuration details.

upstream gitlab-workhorse {
  server unix:/run/gitlab/gitlab-workhorse.socket fail_timeout=0;
}

## Normal HTTP host
server {
  ## Either remove "default_server" from the listen line below,
  ## or delete the /etc/nginx/sites-enabled/default file. This will cause gitlab
  ## to be served if you visit any address that your server responds to, eg.
  ## the ip address of the server (http://x.x.x.x/)n 0.0.0.0:80 default_server;
  listen 0.0.0.0:80;
  listen [::]:80;
  server_name your_url_or_your_ip; ## Replace this with something like gitlab.example.com
  server_tokens off; ## Don't show the nginx version number, a security best practice
  root /usr/share/gitlab/public;

  ## See app/controllers/application_controller.rb for headers set

  ## Individual nginx logs for this GitLab vhost
  access_log  /var/log/nginx/gitlab_access.log;
  error_log   /var/log/nginx/gitlab_error.log;

  location / {
    client_max_body_size 0;
    gzip off;

    ## https://github.com/gitlabhq/gitlabhq/issues/694
    ## Some requests take more than 30 seconds.
    proxy_read_timeout      300;
    proxy_connect_timeout   300;
    proxy_redirect          off;

    proxy_http_version 1.1;

    proxy_set_header    Host                $http_host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto   $scheme;

    proxy_pass http://gitlab-workhorse;
  }
}
netadmin@kmc-b0232:/etc/nginx/sites-available$

gitlab 配置

在 /etc/gitlab 目录下,将以下两个文件各一处配置改成你的本机 IP。(我目前只想在局域网内访问 gitlab 服务器)

  • gitlab.rb:external_url ‘http://your_url_or_your_ip‘
  • gitlab.yml: host: your_ip

修改完后 sudo gitlab-ctl restart (还不清楚与 sudo gitlab-ctl reconfigure 的差异),即可通过 IP 访问到本地 gitlab 服务器。

Logstash采集网站的访问日志

最近又重新接触了一下elastisearch、logstash、kibana,蛮好用的一个日志框架。

同时好久没有更新网站内容、也没怎么关注,虽然有cnzz(umeng)的日志统计功能,但是毕竟是很小一段时间的。要是能够把日志都导出来,就可以用ELK来分析一下自己网站一年来文章的访问情况。

嗯,前阵子买了阿里云的一个VPN服务器,正好可以利用利用。把访问的日志情况通过http发送给logstash,然后存储下来,等过一段时间我们再回来分析分析这些日志。^^

启动Logstash收集服务

  • https://www.elastic.co/blog/introducing-logstash-input-http-plugin
  • https://discuss.elastic.co/t/post-data-to-logstash-using-http-input/69166/8
  • https://www.elastic.co/guide/en/logstash/current/plugins-filters-json.html
~/logstash-6.1.2/bin/logstash -e '
input { 
  http { 
    port => 20000 
    response_headers => {
      "Access-Control-Allow-Origin" => "*"
      "Content-Type" => "application/json"
      "Access-Control-Allow-Headers" => "Origin, X-Requested-With, Content-Type, Accept"
    }
  } 
} 
filter {
  if [message] =~ /^s*$/ {
    drop { }
  }

  json {
    source => "message"
  }
  json {
    source => "location"
    target => "location"
  }
  mutate {
    remove_field => [ "headers" ]
  }
}
output { 
  file { 
    path => "winse-accesslog-%{+YYYY-MM-dd}.log"
    codec => json_lines 
  } 
} 
'

页面发送访问日志记录

$.ajax({
  type: "POST",
  url: "http://SERVER:PORT",
  data: JSON.stringify({
    title: document.title,
    location: JSON.stringify(location),
    referrer: document.referrer,
    userAgent: navigator.userAgent
  }),
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

–END

redis主备同步配置方法

1. 配置主备

假设主机ip:10.136.16.146 port:6789
备机ip:10.136.30.144

我们有两种方式为其配置备机

方法1:修改备机配置文件

redis.conf中增加

daemonize yes
slaveof 10.136.16.146 6789
# 如果主机有密码,则修改下面一行即可
# masterauth <master-password>

在备机上启动redis

redis-server ./tmp/redis.conf

连接上备机reids,执行info replication, 可以看到下面的结果

127.0.0.1:9303> info replication
# Replication
role:slave
master_host:10.136.16.146
master_port:6789
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0

...

此时,我们的主备就已配好。数据会自动同步(包括主机之前的数据),如果之前主机中有数据,此时已可以在备机中读取。

连接主机,执行info replication,可以看到下面结果

10.136.16.146:6789> info replication
# Replication
role:master
connected_slaves:1
slave1:ip=10.136.30.144,port=9303,state=online,offset=40383758059,lag=0
master_repl_offset:40383983932

...

可以看到,主机上已连接一台备份redis,正是我们刚刚启动的那台。

方法2:动态修改备机配置

当然,有时你可能没有权限修改备机redis配置文件或重启redis-server。这时,如果你想配置主备,只需要连上备机redis,执行:

slaveof 10.136.16.146 6789

#主机有密码,还要执行这条
#config set masterauth <password>

同样可以达到配置主备的目的

2. 取消主备

有两种方法取消息主备

  1. 直接在配置文件中去掉slaveof的配置,然后重启redis-server
  2. 连入备机,执行
slaveof no one
  • 1

取消主备后,在备机上执行info replication, 会看到

127.0.0.1:9303> info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

当前机器的角色已不再是slave, 而是master

3. 几个可能用到的参数

  • slave-read-only:两个值,yes/no,用于控制slave是否为只读
  • slave-serve-stale-data: 用于控制当slave和master失去连接或正在进行同步时,slave的行为。
    • yes(默认):仍然正常处理客户端请求,但数据可能是旧的
    • no:向客户端回复SYNC with master in progress

4. 建议

如果配置了主备,建议master开启数据持久化,或者至少不要让master在挂掉后可以自动重启。

可以想象这样一个场景:master未开启持久化,master挂了后被监控重启。这时,master中没有任何数据,slave由于和master同步,上面的数据也将被清空!

Redis数据的备份和还原

未分类

redis属于内存数据库,速度很快,对于有键值对数据存储需求的是非常便利的。

redis数据库的备份和还原也非常的方便。

1、redis数据库备份(导出)

首先进入redis数据库的控制台。

redis-cli

然后输入备份命令

save

未分类

查看一下导出的文件(dumo.rdb)

未分类

2、redis数据库还原(导入)

首先进入redis数据库的控制台。

redis-cli

然后输入如下命令,获取redis的安装路径

CONFIG GET dir

然后在bin的同级目录下找到var,把备份的数据文件(dump.rdb)复制到var目录下,然后重启redis服务即可。

redis未授权访问漏洞

0x00 redis

Redis 是一个高性能的key-value数据库。它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave同步。

0x01 redis未授权访问

Redis因配置不当可以导致未授权访问,被攻击者恶意利用。当前流行的针对Redis未授权访问的一种新型攻击方式,在特定条件下,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器,可导致服务器权限被获取和数据删除、泄露或加密勒索事件发生,严重危害业务正常服务。

0x02 redis未授权访问漏洞产生的原因

Redis 默认情况下,会绑定在 0.0.0.0:6379,这样将会将 Redis 服务暴露到公网上,如果在没有开启认证的情况下,可以导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下可以利用 Redis 的相关方法,可以成功在 Redis 服务器上写入公钥,进而可以使用对应私钥直接登录目标服务器。

0x03 漏洞重现和利用

首先在靶机安装redis并且不设置密码

sudo yum install redis* -y

在靶机安装ssh服务

sudo yum install openssh

在靶机配置redis配置文件,注释掉ip限制,并且设置安全设置为no,使其可以在公网被访问

vi /etc/redis.conf

未分类

未分类

重启redis服务

未分类

测试是否在公网开启

未分类

在靶机打开ssh服务

未分类

在主机本地生成ssh公钥

未分类

连接靶机redis服务,并利用redis未授权访问漏洞在目标服务器/root/.ssh文件夹的authotrized_keys写入刚才创建的ssh公钥

未分类

利用本机的ssh私钥登陆靶机服务器

未分类

0x04 使用openvas对该存在漏洞的系统进行扫描

通过openvas扫描靶机系统,可以得到以下结果:

未分类

未分类

0x05 危害

  • 数据库数据泄露
    Redis 作为数据库,保存着各种各样的数据,如果存在未授权访问的情况,将会导致数据的泄露,其中包含保存的用户信息等。

  • 代码执行
    Redis可以嵌套Lua脚本的特性将会导致代码执行, 危害同其他服务器端的代码执行
    一旦攻击者能够在服务器端执行任意代码, 攻击方式将会变得多且复杂, 这是非常危险的。
    通过Lua代码攻击者可以调用 redis.sha1hex() 函数,恶意利用 Redis 服务器进行 SHA-1 的破解。

  • 敏感信息泄露
    通过 Redis 的 INFO 命令, 可以查看服务器相关的参数和敏感信息, 为攻击者的后续渗透做铺垫。

0x06 应对方案

Redis未授权访问漏洞是一个出现广泛并且危害巨大的漏洞,会直接导致整个服务器沦陷,要预防则需要做到:

(1)禁止使用 root 权限启动 redis 服务;
(2)对 redis 访问启用密码认证,尤其不能使用空密码;
(3)添加 IP 访问限制;
(4)尽可能不对公网直接开放 SSH 服务。

Redis数据备份

Redis数据备份

实例

127.0.0.1:6379> bgsave
OK

这里为什么用bgsave而不使用save,请参考文章:

http://www.chenxm.cc/post/526.html

Redis恢复数据

1、 获取redis备份目录

127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "D:\software\Redis"
127.0.0.1:6379>

以上命令 CONFIG GET dir 输出的 redis 备份目录为 /usr/local/redis/bin。

2、 停止redis服务

src/redis-cli -p 6379 shutdown

src是redis安装目录

3、拷贝redis备份文件(dump.rdb)到 /usr/local/redis/bin目录下

4、重新启动redis服务

linux

src/redis-server redis.conf

windows

src/redis-server redis.windows.conf

实际上只要redis重启,会自动读取备份目录下dump.rdb文件,如果有该文件,会自动恢复数据。

5、查看是否redis恢复数据

$ src/redis-cli
127.0.0.1:6379> keys *
 1) "k1"
 2) "k2"
 3) "k3"
 4) "k4"
 5) "k5"

redis安装流程

安装:

1、安装依赖包

yum -y install gcc gcc-c++ libstdc++-devel tcl

2、获取安装文件并解压文件

tar -zvx -f redis-3.2.4.tar.gz

3、进入目录

cd redis-3.2.4

4、编译

make

5、安装

make install

6、设置配置文件路径

mkdir -p /etc/redis 
cp redis.conf /etc/redis

7、修改配置文件

vi /etc/redis/redis.conf 

仅修改: daemonize yes

8、启动

/usr/local/bin/redis-server /etc/redis/redis.conf

9、查看启动

ps -ef | grep redis

10、使用客户端

redis-cli

set name hello 
OK 
get name 
“hello”

测试:

127.0.0.1:6379> hset 10001 name zhangsan 
(integer) 1 
127.0.0.1:6379> keys * 
1) “10001” 
127.0.0.1:637 
127.0.0.1:6379> hset 10001 address shanghai 
(integer) 1 
127.0.0.1:6379> HGETALL 10001 
1) “name” 
2) “zhangsan” 
3) “address” 
4) “shanghai”

node1:6379> select 1 
node1:6379[1]> flushall 
OK 
node1:6379[1]> keys * 
(empty list or set)

Linux终端前缀变成-bash-4.2#解决办法

这个问题困扰了我很久,每次登陆终端提示就是这样子:

Last login: Fri Jan 19 15:57:15 2018 from 
Welcome to JCLOUD Elastic Compute Service
-bash-4.2#

后来以为是软件环境问题,找到了个解决办法:

终端输入:PS1="[root@localhost ~]"

之后看起来是解决了这个问题,但是一直是这样子的提示,进出目录该有的提示都没有,就是个摆设。

后来找到了正确的解决方法。

这个问题出现的原因是.bashrc文件被破坏,导致里面没有该有的内容
那是什么内容呢?就是这个:

PS1='[u@h W]$ '

因为我把rm改造为mv之后,没有加上这个代码,导致读取不到,所以就显示bash-4.2,把这个代码加入.bashrc之后,source .bashrc即可恢复。

上代码示例:

PS1='[u@h W]$ '>>.bashrc
source .bashrc

这样就解决了这个问题,希望对出现此问题的有帮助。

解释下shell下的bash中的test记忆

解决问题

  • test有几种写法
  • [ -f 1.txt ] 为什么在[]前后必须有空格

写法

if [ -f 1.txt ];then echo "hello";fi

if [ -f 1.txt ];then
    echo "hello"
fi

if [ -f 1.txt ];
then
    echo "hello"
fi

if [ -f 1.txt ]
then echo "hello"
fi

if [ -f 1.txt]
then
    echo "hello"
fi

总结

  • [ -f 1.txt ] ‘[‘是命令名 ’-f 1.txt ]’是参数,参数是用空格分割的,这是一个命令
  • if then后都是跟的命令
  • ;和回车都可以分割命令,多个命令在一行要用;分割