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 FmstratENV 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上げました。
コメント