DockerでAD-Samba構築【その2:冗長構成編】
前回DockerでSamba-ADを1台構成で構築したんですが、やはりADだと2台以上で構成するんだよなぁふつうはということで5年前の内容を参照しつつこちらのDockerファイルをほぼ丸パクリしてUbuntu20.04LTSの最新版とまぁ一応Version4.11.6という現時点の最新版のSambaをインストールしてADの冗長構成を組むというパターンでDockerやってみました。開放するポートが多すぎるのと1台で複数IPやると効率悪そうなのでホストモードにして2台構成にしてます。
丁度、こんなイメージです
ももともとはCALのかからないADが欲しいというのが動機でもあったんですが、そしてもう1台のPCにWindowsの仮想マシンが2台いるのでこいつらをドメインに参加させて色々と実験したいわけです。
◆ディレクトリ構成、Version等
. |-- docker-compose.yml |-- image | |-- Dockerfile | |-- LICENSE.md | |-- README.md | |-- init.sh | `-- ubuntu-join-domain.sh 20.04.2 LTS (Focal Fossa) Docker version 20.10.8, build 3967b7d docker-compose version 1.29.1, build c34c88b2
◆構築手順
1.初期設定(メインAD機、サブAD機共通作業)
・仮想マシン追加構築
Hyper-Vでエクスポート、インポートにて仮想マシン構築
・ネットワーク設定
#IPアドレス変更
$ sudo vi /etc/netplan/00-installer-config.yaml
---------------------------
# This is the network config written by 'subiquity'
network:
ethernets:
eth0:
addresses:
- 192.168.0.10/24 #←該当のADのIPに変更する
gateway4: 192.168.0.1
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
version: 2
---------------------------
$ sudo netplan apply
#ホスト名変更
$ sudo hostnamectl set-hostname ad-srv-name.yourdomain
$ sudo vi /etc/cloud/cloud.cfg
---------------------------
# This will cause the set+update hostname module to not operate (if true)
preserve_hostname: true #変更
---------------------------
$ sudo vi /etc/hosts
---------------------------
127.0.0.1 localhost
127.0.0.1 ad-srv-name.yourdomain #追記
127.0.1.1 ad-srv-name #修正
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
---------------------------
#resolvd停止
$ sudo vi /etc/systemd/resolved.conf
----------------------------
[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#DNSOverTLS=no
#Cache=no-negative
#DNSStubListener=yes
DNSStubListener=no #修正
#ReadEtcHosts=yes
----------------------------
$ cd /etc
$ sudo rm -Rf resolv.conf
$ sudo ln -sf ../run/systemd/resolve/resolv.conf resolv.conf
$ sudo systemctl restart systemd-resolved
$ sudo shutdown -r now
#SambaAD使用ポート開放
$ vi firewall_port_open.sh
-------------------------------
#/bin/bash
sudo ufw allow 42
sudo ufw allow 137
sudo ufw allow 138
sudo ufw allow 139
sudo ufw allow domain
sudo ufw allow kerberos
sudo ufw allow ldap
sudo ufw allow loc-srv
sudo ufw allow 1024
sudo ufw allow 3268
sudo ufw allow 3269
sudo ufw allow 749
sudo ufw allow 636
sudo ufw allow 445
sudo ufw allow 464
sudo ufw allow 5722
sudo ufw allow 49152:65535/tcp
-------------------------------
$ chmod 755 firewall_port_open.sh
$ ./firewall_port_open.sh
$ sudo ufw status
状態: アクティブ
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
42 ALLOW Anywhere
137 ALLOW Anywhere
138 ALLOW Anywhere
139 ALLOW Anywhere
53 ALLOW Anywhere
88 ALLOW Anywhere
389 ALLOW Anywhere
135/tcp ALLOW Anywhere
1024 ALLOW Anywhere
3268 ALLOW Anywhere
3269 ALLOW Anywhere
749 ALLOW Anywhere
636 ALLOW Anywhere
445 ALLOW Anywhere
464 ALLOW Anywhere
5722 ALLOW Anywhere
49152:65535/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
42 (v6) ALLOW Anywhere (v6)
137 (v6) ALLOW Anywhere (v6)
138 (v6) ALLOW Anywhere (v6)
139 (v6) ALLOW Anywhere (v6)
53 (v6) ALLOW Anywhere (v6)
88 (v6) ALLOW Anywhere (v6)
389 (v6) ALLOW Anywhere (v6)
135/tcp (v6) ALLOW Anywhere (v6)
1024 (v6) ALLOW Anywhere (v6)
3268 (v6) ALLOW Anywhere (v6)
3269 (v6) ALLOW Anywhere (v6)
749 (v6) ALLOW Anywhere (v6)
636 (v6) ALLOW Anywhere (v6)
445 (v6) ALLOW Anywhere (v6)
464 (v6) ALLOW Anywhere (v6)
5722 (v6) ALLOW Anywhere (v6)
49152:65535/tcp (v6) ALLOW Anywhere (v6)
2.Dockerイメージ準備(メインAD機、サブAD機共通)
結構ダイナミックにポートを使用するので、ホストモードにてDockerを利用することとした。通常はこんな使い方しないんだろうけど・・・
# Dockerイメージダウンロード
$ mkdir docker
$ cd docker/
$ git clone https://github.com/Fmstrat/samba-domain.git image
$ vi image/init.sh
※init.shについてはKerberosのconfig差替状態なので大幅修正が必要
--------------------------------------------
#!/bin/bash
set -e
appSetup () {
# Set variables
DOMAIN=${DOMAIN:-SAMDOM.LOCAL}
DOMAINPASS=${DOMAINPASS:-youshouldsetapassword}
JOIN=${JOIN:-false}
JOINSITE=${JOINSITE:-NONE}
MULTISITE=${MULTISITE:-false}
NOCOMPLEXITY=${NOCOMPLEXITY:-false}
INSECURELDAP=${INSECURELDAP:-false}
DNSFORWARDER=${DNSFORWARDER:-NONE}
HOSTIP=${HOSTIP:-NONE}
KDCMAIN=${KDCMAIN:-yourkdcadmin}
KDCSUB=${KDCSUB:-yourkdc}
LDOMAIN=${DOMAIN,,}
UDOMAIN=${DOMAIN^^}
URDOMAIN=${UDOMAIN%%.*}
# If multi-site, we need to connect to the VPN before joining the domain
if [[ ${MULTISITE,,} == "true" ]]; then
/usr/sbin/openvpn --config /docker.ovpn &
VPNPID=$!
echo "Sleeping 30s to ensure VPN connects ($VPNPID)";
sleep 30
fi
# Set host ip option
if [[ "$HOSTIP" != "NONE" ]]; then
HOSTIP_OPTION="--host-ip=$HOSTIP"
else
HOSTIP_OPTION=""
fi
# Set up samba
mv /etc/krb5.conf /etc/krb5.conf.orig
echo "[libdefaults]" > /etc/krb5.conf
echo " dns_lookup_realm = false" >> /etc/krb5.conf
echo " dns_lookup_kdc = true" >> /etc/krb5.conf
echo " default_realm = ${UDOMAIN}" >> /etc/krb5.conf
echo "[realms]" >> /etc/krb5.conf
echo " ${UDOMAIN} = {" >> /etc/krb5.conf
echo " kdc = ${KDCMAIN}.${UDOMAIN}" >> /etc/krb5.conf
echo " kdc = ${KDCSUB}.${UDOMAIN}" >> /etc/krb5.conf
echo " admin_server = ${KDCMAIN}.${UDOMAIN}" >> /etc/krb5.conf
echo " }" >> /etc/krb5.conf
echo "[domain_realm]" >> /etc/krb5.conf
echo " .${LDOMAIN} = ${UDOMAIN}" >> /etc/krb5.conf
echo " ${LDOMAIN} = ${UDOMAIN}" >> /etc/krb5.conf
# If the finished file isn't there, this is brand new, we're not just moving to a new container
if [[ ! -f /etc/samba/external/smb.conf ]]; then
mv /etc/samba/smb.conf /etc/samba/smb.conf.orig
if [[ ${JOIN,,} == "true" ]]; then
if [[ ${JOINSITE} == "NONE" ]]; then
samba-tool domain join ${LDOMAIN} DC -U"${URDOMAIN}\administrator" --password="${DOMAINPASS}" --dns-backend=SAMBA_INTERNAL
else
samba-tool domain join ${LDOMAIN} DC -U"${URDOMAIN}\administrator" --password="${DOMAINPASS}" --dns-backend=SAMBA_INTERNAL --site=${JOINSITE}
fi
else
samba-tool domain provision --use-rfc2307 --domain=${URDOMAIN} --realm=${UDOMAIN} --server-role=dc --dns-backend=SAMBA_INTERNAL --adminpass=${DOMAINPASS} ${HOSTIP_OPTION}
if [[ ${NOCOMPLEXITY,,} == "true" ]]; then
samba-tool domain passwordsettings set --complexity=off
samba-tool domain passwordsettings set --history-length=0
samba-tool domain passwordsettings set --min-pwd-age=0
samba-tool domain passwordsettings set --max-pwd-age=0
fi
fi
if [[ $DNSFORWARDER != "NONE" ]]; then
sed -i "/dns forwarder/d" /etc/samba/smb.conf
sed -i "/\[global\]/a \
\\\tdns forwarder = ${DNSFORWARDER}\
" /etc/samba/smb.conf
fi
if [[ ${INSECURELDAP} == "true" ]]; then
sed -i "/\[global\]/a \
\\\tldap server require strong auth = no\
" /etc/samba/smb.conf
fi
# Once we are set up, we'll make a file so that we know to use it if we ever spin this up again
cp /etc/samba/smb.conf /etc/samba/external/smb.conf
else
cp /etc/samba/external/smb.conf /etc/samba/smb.conf
fi
# Set up supervisor
echo "[supervisord]" > /etc/supervisor/conf.d/supervisord.conf
echo "nodaemon=true" >> /etc/supervisor/conf.d/supervisord.conf
echo "" >> /etc/supervisor/conf.d/supervisord.conf
echo "[program:samba]" >> /etc/supervisor/conf.d/supervisord.conf
echo "command=/usr/sbin/samba -i" >> /etc/supervisor/conf.d/supervisord.conf
if [[ ${MULTISITE,,} == "true" ]]; then
if [[ -n $VPNPID ]]; then
kill $VPNPID
fi
echo "" >> /etc/supervisor/conf.d/supervisord.conf
echo "[program:openvpn]" >> /etc/supervisor/conf.d/supervisord.conf
echo "command=/usr/sbin/openvpn --config /docker.ovpn" >> /etc/supervisor/conf.d/supervisord.conf
fi
if [[ ${JOIN,,} == "true" ]]; then
echo "" >> /etc/supervisor/conf.d/supervisord.conf
echo "[program:cron]" >> /etc/supervisor/conf.d/supervisord.conf
echo "command=/usr/sbin/cron" >> /etc/supervisor/conf.d/supervisord.conf
fi
appStart
}
appStart () {
/usr/bin/supervisord
}
case "$1" in
start)
if [[ -f /etc/samba/external/smb.conf ]]; then
cp /etc/samba/external/smb.conf /etc/samba/smb.conf
appStart
else
echo "Config file is missing."
fi
;;
setup)
# If the supervisor conf isn't there, we're spinning up a new container
if [[ -f /etc/supervisor/conf.d/supervisord.conf ]]; then
appStart
else
appSetup
fi
;;
esac
exit 0
--------------------------------------------
#Dockerfile修正
$ vi image/Dockerfile
※下記の通り修正する。(ホストモードで使用する)
--------------------------------------------
FROM ubuntu:latest
MAINTAINER Fmstrat
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y
# Install all apps
# The third line is for multi-site config (ping is for testing later)
RUN apt-get install -y pkg-config
RUN apt-get install -y attr acl samba smbclient ldap-utils winbind libnss-winbind libpam-winbind krb5-user krb5-kdc supervisor tzdata vim
RUN apt-get install -y openvpn inetutils-ping
# Set up script and run
ADD init.sh /init.sh
RUN chmod 755 /init.sh
CMD /init.sh setup
EXPOSE 42
EXPOSE 53
EXPOSE 53/udp
EXPOSE 88
EXPOSE 88/udp
EXPOSE 123
EXPOSE 135
EXPOSE 137-138/udp
EXPOSE 139
EXPOSE 389
EXPOSE 389/udp
EXPOSE 445
EXPOSE 464
EXPOSE 464/udp
EXPOSE 636
EXPOSE 1024-1044
EXPOSE 3268-3269
EXPOSE 5722:5722
EXPOSE 49152-65535
--------------------------------------------
3-1.メインAD機docker-composeファイル作成
メインAD側は通常のdocker-compose.ymlを使用する
$ vi docker-compose.yml
------------------------------------
version: '3.9'
services:
# see: https://github.com/Fmstrat/samba-domain
ad_main_samba:
build: ./image
image: mainsamba
container_name: main_samba_ad
volumes:
- ./data/:/var/lib/samba
- ./config/samba:/etc/samba/external
- ./log:/var/log/samba
environment:
- DOMAIN=${AD_DOMAIN}
- DOMAINPASS=${AD_DOMAIN_PASSWORD}
- DNSFORWARDER=${EXT_DNS1_ADDR}
- HOSTIP=${ADS_ADDR}
- KDCMAIN=${MAIN_AD}
- KDCSUB=${SUB_AD}
- INSECURELDAP=true
- TZ=Asia/Tokyo
network_mode: host
dns_search:
- ${DOMAIN_NAME}
dns:
- ${ADS_ADDR}
- ${EXT_DNS1_ADDR}
- ${EXT_DNS2_ADDR}
extra_hosts:
- ${HOST_NAME}.${DOMAIN_NAME}:${ADS_ADDR}
hostname: ${HOST_NAME}
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
privileged: true
restart: always
-------------------------------
$ vi .env
----------------------
ADS_ADDR=192.168.0.10
AD_DOMAIN=YOURADDOMAIN
EXT_DNS1_ADDR=8.8.8.8
EXT_DNS2_ADDR=8.8.4.4
AD_DOMAIN_PASSWORD=YourPassword
MAIN_AD=mainadhostname
HOST_NAME=mainadhostname
SUB_AD=subadhostname
DOMAIN_NAME=youraddomain
----------------------
$ docker-compose up -d
3-2.サブAD機docker-composeファイル準備
サブAD側はcronを仕込むのでファイルを1つ準備し、docker-composeはjoin箇所を修正してサブドメインコントローラとして参加する様にしている。
#SYSVOL同期用cron用ファイル準備
$ echo "1-59/15 * * * * root samba-tool ntacl sysvolreset" > image/sysvol-cron
#docker-compose.yml準備
$ vi docker-compose.yml
------------------------------------
version: '3.9'
services:
ad_sub_samba:
build: ./image
image: subsamba
container_name: sub_samba_ad
volumes:
- ./data/:/var/lib/samba
- ./config/samba:/etc/samba/external
- ./log:/var/log/samba
environment:
- DOMAIN=${AD_DOMAIN}
- DOMAINPASS=${AD_DOMAIN_PASSWORD}
- JOIN=true
- DNSFORWARDER=${EXT_DNS1_ADDR}
- HOSTIP=${ADS_ADDR}
- KDCMAIN=${MAIN_AD}
- KDCSUB=${SUB_AD}
- INSECURELDAP=true
- TZ=Asia/Tokyo
network_mode: host
dns_search:
- ${DOMAIN_NAME}
dns:
- ${MAINAD_IP}
- ${EXT_DNS1_ADDR}
- ${EXT_DNS2_ADDR}
extra_hosts:
- ${HOST_NAME}.${DOMAIN_NAME}:${ADS_ADDR}
hostname: ${HOST_NAME}
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
privileged: true
restart: always
------------------------------------
$ vi .env
------------------------------------
ADS_ADDR=192.168.0.20
MAINAD_IP=192.168.0.10
AD_DOMAIN=YOURADDOMAIN
EXT_DNS1_ADDR=8.8.8.8
EXT_DNS2_ADDR=8.8.4.4
AD_DOMAIN_PASSWORD=YourPassword
MAIN_AD=mainadhostname
HOST_NAME=subadhostname
SUB_AD=subadhostname
DOMAIN_NAME=youraddomain
------------------------------------
$ docker-compose up -d
4.SYSVOLディレクトリ同期用設定
メインADがFSMOなのでメインAD機のホストからサブADにrsyncをかける
#sshユーザグループにsudo可能ユーザ追加(メインADホスト機とサブADホスト機両方で実行) $ sudo usermod -aG sshgrp user #秘密鍵と公開鍵作成(サブADホスト機側で作成) $ ssh-keygen -t rsa -f /home/user/.ssh/rsync-gpo Generating public/private rsa key pair. Created directory '/home/user/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: $ chmod -R 700 .ssh $ cat .ssh/rsync-gpo.pub ssh-rsa XXXXX #公開鍵登録(メインADホスト機で実行) $ cd $ mkdir -m700 .ssh $ vi .ssh/authorized_keys ※サブ機のrsync-gpo.pubをコピー $ chmod 700 .ssh/authorized_keys #sudo権限設定(メインADホスト機とサブADホスト機両方で実行) $ sudo visudo ----------------------------------------------- # directly modifying this file. # # See the man page for details on how to write a sudoers file. # Defaults env_reset Defaults mail_badpass Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin" Defaults env_keep += "SSH_AUTH_SOCK" #↓追記 Defaults env_keep += "SSH_AUTH_SOCK" #↓最後尾に追加 # sysvol replicate Defaults!/usr/bin/rsync !requiretty user ALL=(ALL) NOPASSWD: /usr/bin/rsync ----------------------------------------------- #サブADホスト機で接続確認後にcrontab設定 $ sudo rsync --dry-run -aAXu -e "ssh -i /home/user/.ssh/rsync-gpo" --rsync-path='sudo rsync' user@192.168.0.10:/home/user/docker/data/sysvol/youraddomain/ /home/user/docker/data/sysvol/youraddomain/ $ sudo crontab -e ----------------------------------------------- */15 * * * * sudo rsync -aAXu -e "ssh -i /home/user/.ssh/rsync-gpo" --rsync-path='sudo rsync' user@192.168.0.10:/home/user/docker/data/sysvol/nishimura.local/ /home/user/docker/data/sysvol/nishimura.local/ -----------------------------------------------
◆参考サイト
・Docker-Composeネットワーク
https://inocop.hatenablog.com/entry/2018/12/18/131526
https://hakengineer.xyz/2018/07/29/post-1475/
https://knowledge.sakura.ad.jp/23899/
https://knowledge.sakura.ad.jp/26522/
https://matsuand.github.io/docs.docker.jp.onthefly/compose/networking/
https://pj-doaa.hatenablog.com/entry/2019/09/04/144520
https://togattti.hateblo.jp/entry/2019/06/30/104931
https://docs.docker.jp/engine/reference/commandline/network_create.html
・ホスト側の固定IPアドレス設定
https://qiita.com/zen3/items/757f96cbe522a9ad397d
https://www.komee.org/entry/2018/06/12/181400
https://qiita.com/shora_kujira16/items/31d09b373809a5a44ae5
https://blog.jicoman.info/2020/06/how-to-resolve-problem-of-name-resolution-to-local-on-ubuntu-2004/
・Samba-AD Docker
https://qiita.com/hrkt/items/68ae33cdfae4713d7566
http://sheepdogjam.cocolog-nifty.com/blog/2020/01/post-808d61.html
https://github.com/hobby-labs/samba-ad-container#prerequisite-of-primarysecondary-dc
https://github.com/naturalis/docker-samba
・Samba-AD
https://torutk.hatenablog.jp/entry/20130301/p1
https://www.cbreeze.info/pc1/pc765.html
https://wiki.samba.org/index.php/Samba_AD_DC_Port_Usage
https://www.rem-system.com/samba-410-ad/
・DNS切り分け関連
https://dnsops.jp/event/20120831/dns-troubleshoot-1.pdf
・Docker内でcron
https://qiita.com/YuukiMiyoshi/items/bb7f14436d60d4bd8a8b
https://codehero.jp/docker/37458287/how-to-run-a-cron-job-inside-a-docker-container
・SYSVOL同期
https://dev.tranquil.it/samba/en/samba_fundamentals/samba_ad_replication.html
https://centossrv.com/activedirectory-replication.shtml
https://ja.linux-console.net/?p=2270
https://fuminori14.hatenablog.com/entry/20121002/1349184746
まぁひとまずこれでやろうとしていたことはできたんだけど、この環境構築終わらせるまでに3ヶ月くらい時間溶かしてて非常に泣きそうになりました。そしてここからAlfrescoとかRedmineとこのSamba-ADを連携させてみたりしようとしているんですが、しかしながら仮想のVMでこんなの組まなくても、最近はAZureADとかあるからおとなしくそっち使えよという話でしょうな。そしてホストモードでコンテナ使うとあまり意味がないということを痛感いたしました・・・。次はいよいよAlfrescoだな
一応、GitHub上げました。

コメント