First version

main 1.0
rohhie 2022-10-30 10:59:26 +09:00
commit 547ef493ba
14 changed files with 927 additions and 0 deletions

9
DockerfileIPv4 Normal file
View File

@ -0,0 +1,9 @@
FROM alpine:latest
RUN apk add dhcp-server-vanilla samba-dc krb5 bash bind-tools tzdata && \
touch /var/lib/dhcp/dhcpd.leases
ADD v4/entrypoint.sh /
ADD v4/dhcpd.conf /etc/dhcp/
ADD dhcp-dyndns.sh /usr/local/bin/
ADD ssoauth.keytab /etc/
ADD krb5.conf /etc/
ENTRYPOINT ["/entrypoint.sh"]

11
DockerfileIPv6 Normal file
View File

@ -0,0 +1,11 @@
FROM alpine:latest
RUN apk add dhcp-server-vanilla radvd samba-dc krb5 bash bind-tools tzdata && \
touch /var/lib/dhcp/dhcpd.leases && \
mkdir /run/radvd
ADD v6/entrypoint.sh /
ADD v6/dhcpd.conf /etc/dhcp/
ADD v6/radvd.conf /etc/
ADD dhcp-dyndns.sh /usr/local/bin/
ADD ssoauth.keytab /etc/
ADD krb5.conf /etc/
ENTRYPOINT ["/entrypoint.sh"]

9
LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2022 rohhie@rohhie.net
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

44
LICENSE_dhcp-dyndns.sh Normal file
View File

@ -0,0 +1,44 @@
# Version: 0.9.5
#
# Copyright (C) Rowland Penny 2020-2022
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ---
#
# Revised 2022-10-22, Rohhie, as follows:
# - logs to stderr.
# - Server name, domain name and DNS admin name are now specified in
# environment variables.
# - Since the assumption is that the user has been created,
# the test logic was removed.
# - Moved the parameter "-s" in the klist command.
# - When expired, the host name is retrieved from the target IP address.
# - Added processing to support IPv6
# (works as far as I want to use it in my home lab).
#
# Copyright (C) rohhie@rohhie.net 2022
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

96
README.md Normal file
View File

@ -0,0 +1,96 @@
# Samba-ad-dc-ddns-docker
## 概要
Samba ad dcと連携するDHCPサーバーをDockerで気軽に利用する。
## 構築方法
### ダウンロード
このリポジトリからソースをダウンロードする。
```
git clone https://gitea.rohhie.net/rohhie/samba-ad-dc-ddns-docker.git ddns
cd ddns
```
### 動作条件を設定
#### コンテナ
docker-compose.ymlには、IPv4とIPv6の2つのコンテナを定義してある。
どちらか一方を利用する場合は、使わない方をコメントアウトしておく。
それぞれの動作条件を設定する。
| 変数名 | 設定内容 |
|------------|--------------------------------------------------------------------------|
| DHCPIF | 使用するネットワークインターフェースを設定。空白で区切って複数指定可能。 |
| DHCPSERVER | Samba AD DCのホスト名を指定。名前解決できる(はず)。 |
| DHCPDOMAIN | ドメインのFQDNを指定。 |
| DHCPDNSADM | DnsAdminsのユーザー名を指定。 |
| DHCPDBGFLG | "true"を指定すると、標準出力にデバッグ情報が出力される。 |
#### IPv4
v4ディレクトリにdhcpd.confがあるので、これを適宜書き換える。
#### IPv6
v6ディレクトリにdhcpd.confとradvd.confがあるので、適切に設定。
radvd.confでは、使用するネットワークインターフェースの設定があるので、環境変数DHCPIFとあわせて設定しておく。
#### Kerberos
krb5.confをSamba ad dcにアクセスできるように作成。
#### keytab
Samba ad dcでDnsAdminに所属するユーザーのkeytabを取り出す。
ホームラボでは、Samba ad dc立ち上げ時にssoauthというユーザーを作りDnsAdminにしたので、これを使っている。
新たにユーザーを作っても良いし、既存のユーザーを使っても良い。
```
<username>.keytab
```
という名前で保管しておく。
ホームラボではssoauth.keytabという名前で保管している。
#### dhcp-dyndns.sh
これは、Samba Wiki(https://wiki.samba.org/index.php/Configure_DHCP_to_update_DNS_records)にあるスクリプトをベースにして、IPv6の処理を追加している。
ユーザーはssoauthとしているので、DnsAdminのユーザー名に置換して使用する。
### ファイアウォールの設定
ファイアウォールを設定するスクリプトを実行する。
このスクリプトではIPv6のみ開放している。
IPv4は開放しなくてもうまく動いている。
```
sudo ./setufw.sh
```
何らかの理由で設定を解除するなら、以下を実行する。
```
sudo ./setufw.sh delete
```
### コンテナを起動
コンテナを構築して起動する。
```
sudo docker compose up -d --bulid
```
## その他
細かな設定手順や使い方は、メインサイト参照。
https://rohhie.net/samba-ad-dc-dynamicdns/
## ライセンス
MIT
ただし、dhcp-dyndns.shだけはソースコード参照。
変更点は原作に準じてGPL3.0以降とする。

509
dhcp-dyndns.sh Executable file
View File

@ -0,0 +1,509 @@
#!/bin/bash
# On FreeBSD change the above line to #!/usr/local/bin/bash
#
# /usr/local/bin/dhcp-dyndns.sh
#
# This script is for secure DDNS updates on Samba,
# it can also add the 'macAddress' to the Computers object.
#
# Version: 0.9.5
#
# Copyright (C) Rowland Penny 2020-2022
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Revised 2022-10-22, Rohhie, as follows:
# - ログをstderrに出力するようにした。
# - サーバー名とドメイン名、DNS管理者ユーザー名を環境変数で指定するようにした。
# - ユーザーは作ってある前提なのでテストロジックを削除した。
# - klistの-s指定をファイル名の前に移動した。
# - 期限切れで削除になる時、対象IPアドレスからホスト名を取得するようにした。
# - IPv6に対応する処理を追加した(ホームラボで使いたい範囲で動く程度)。
# You may need to ensure that you have a useful path
# If you have 'path' problems, Uncomment the next line and adjust for
# your setup e.g. self-compiled Samba
#export PATH=/usr/local/samba/bin:/usr/local/samba/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
##########################################################################
# #
# You can optionally add the 'macAddress' to the Computers object. #
# Add '$DHCPDNSADM' to the 'Domain Admins' group if used #
# Change the next line to 'yes' to make this happen #
Add_macAddress='no'
# #
##########################################################################
# On FreeBSD change this to /usr/local/etc/<USERNAME>.keytab
keytab=/etc/$DHCPDNSADM.keytab
usage()
{
cat <<-EOF
USAGE:
$(basename "$0") add ip-address dhcid|mac-address hostname
$(basename "$0") delete ip-address dhcid|mac-address
EOF
}
_KERBEROS()
{
# get current time as a number
test=$(date +%d'-'%m'-'%y' '%H':'%M':'%S)
# Note: there have been problems with this
# check that 'date' returns something like
# Check for valid kerberos ticket
#logger -s "${test} [dyndns] : Running check for valid kerberos ticket"
klist -c -s "${KRB5CCNAME}"
ret="$?"
if [ $ret -ne 0 ]
then
logger -s "${test} [dyndns] : Getting new ticket, old one has expired"
# On FreeBSD change the -F to --no-forwardable
kinit -F -k -t $keytab "${SETPRINCIPAL}"
ret="$?"
if [ $ret -ne 0 ]
then
logger -s "${test} [dyndns] : dhcpd kinit for dynamic DNS failed"
exit 1
fi
fi
}
rev_zone_info()
{
local RevZone="$1"
local IP="$2"
local rzoneip
local rzonenum
if [[ $RevZone =~ .+"in-addr.arpa"$ ]]; then
if [ $3 = "AAAA" ]; then
ZoneIP="-no match-"
return;
fi
rzoneip="${RevZone%.in-addr.arpa}"
else
if [ $3 = "A" ]; then
ZoneIP="-no match-"
return;
fi
rzoneip="${RevZone%.ip6.arpa}"
fi
unset ZoneIP
unset RZIP
unset IP2add
if [ $3 = "A" ]; then
rzonenum=$(echo "$rzoneip" | tr '.' '\n')
declare -a words
for n in $rzonenum
do
words+=("$n")
done
local numwords="${#words[@]}"
case "$numwords" in
1)
# single ip rev zone '192'
ZoneIP=$(echo "${IP}" | awk -F '.' '{print $1}')
RZIP="${rzoneip}"
IP2add=$(echo "${IP}" | awk -F '.' '{print $4"."$3"."$2}')
;;
2)
# double ip rev zone '168.192'
ZoneIP=$(echo "${IP}" | awk -F '.' '{print $1"."$2}')
RZIP=$(echo "${rzoneip}" | awk -F '.' '{print $2"."$1}')
IP2add=$(echo "${IP}" | awk -F '.' '{print $4"."$3}')
;;
3)
# triple ip rev zone '0.168.192'
ZoneIP=$(echo "${IP}" | awk -F '.' '{print $1"."$2"."$3}')
RZIP=$(echo "${rzoneip}" | awk -F '.' '{print $3"."$2"."$1}')
IP2add=$(echo "${IP}" | awk -F '.' '{print $4}')
;;
*)
# should never happen
exit 1
;;
esac
else
local v6ip=$(echo -n $2 | sed "s/://g")
local v6zn=$(echo -n $rzoneip | sed "s/\.//g" | rev)
if [[ $v6ip =~ "$v6zn".+ ]]; then
ZoneIP=$2
RZIP="${ZoneIP}"
IP2add=$(echo -n $v6ip | sed "s/$v6zn\(.\+\)/\1/" | rev | sed "s/\(.\)/\1./g" | sed "s/.$//")
rzoneip="${RevZone%.ip6.arpa}"
else
ZoneIP="-no match-"
return;
fi
fi
}
ipv6_short_to_long () {
divaddr=$(echo -n $1 | sed "s/::/:-:/")
local IFSBAK=$IFS
IFS=: divaddr=($divaddr)
IFS=$IFSBAK
defaddr=()
for element in "${divaddr[@]}"; do
if [ $element = "-" ]; then
padmax=$((8-${#divaddr[@]}))
for (( i=0; i<=$padmax; i++ ))
do
defaddr+=("0000")
done
else
padding="0000${element}"
defaddr+=(${padding: -4})
fi
done
longaddr=$(echo -n ${defaddr[@]} | sed "s/ /:/g")
echo $longaddr
}
BINDIR=$(samba -b | grep 'BINDIR' | grep -v 'SBINDIR' | awk '{print $NF}')
[[ -z $BINDIR ]] && printf "Cannot find the 'samba' binary, is it installed ?\\nOr is your path set correctly ?\\n"
WBINFO="$BINDIR/wbinfo"
SAMBATOOL=$(command -v samba-tool)
[[ -z $SAMBATOOL ]] && printf "Cannot find the 'samba-tool' binary, is it installed ?\\nOr is your path set correctly ?\\n"
MINVER=$($SAMBATOOL -V | grep -o '[0-9]*' | tr '\n' ' ' | awk '{print $2}')
if [ "$MINVER" -gt '14' ]
then
KTYPE="--use-kerberos=required"
else
KTYPE="-k yes"
fi
# DHCP Server hostname
#Server=$(hostname -s)
Server=${DHCPSERVER}.${DHCPDOMAIN}
# DNS domain
#domain=$(hostname -d)
domain=${DHCPDOMAIN}
if [ -z "${domain}" ]
then
logger -s "Cannot obtain domain name, is DNS set up correctly?"
logger -s "Cannot continue... Exiting."
exit 1
fi
# Samba realm
REALM="${domain^^}"
# krbcc ticket cache
export KRB5CCNAME="/tmp/dhcp-dyndns.cc"
# Kerberos principal
SETPRINCIPAL="${DHCPDNSADM}@${REALM}"
# Kerberos keytab as above
# krbcc ticket cache : /tmp/dhcp-dyndns.cc
#TESTUSER="$($WBINFO -u | grep $DHCPDNSADM)"
#if [ -z "${TESTUSER}" ]
#then
# logger -s "No AD dhcp user exists, need to create it first.. exiting."
# logger -s "you can do this by typing the following commands"
# logger -s "kinit Administrator@${REALM}"
# logger -s "$SAMBATOOL user create $DHCPDNSADM --random-password --description='Unprivileged user for DNS updates via ISC DHCP server'"
# logger -s "$SAMBATOOL user setexpiry $DHCPDNSADM --noexpiry"
# logger -s "$SAMBATOOL group addmembers DnsAdmins $DHCPDNSADM"
# exit 1
#fi
# Check for Kerberos keytab
if [ ! -f /etc/$DHCPDNSADM.keytab ]
then
logger -s "Required keytab $keytab not found, it needs to be created."
logger -s "Use the following commands as root"
logger -s "$SAMBATOOL domain exportkeytab --principal=${SETPRINCIPAL} $keytab"
logger -s "chown XXXX:XXXX $keytab"
logger -s "Replace 'XXXX:XXXX' with the user & group that dhcpd runs as on your distro"
logger -s "chmod 400 $keytab"
exit 1
fi
# Variables supplied by dhcpd.conf
action="$1"
DHCID="$3"
name="${4%%.*}"
if [ "$5" = "-IPv6-" ]; then
ip=$(ipv6_short_to_long $2)
AorAAAA="AAAA"
else
ip="$2"
AorAAAA="A"
fi
# Exit if no ip address
if [ -z "${ip}" ]
then
usage
exit 1
fi
# Exit if no computer name supplied, unless the action is 'delete'
if [ -z "${name}" ]
then
if [ "${action}" = "delete" ]
then
name=$(host -t PTR "${ip}" | awk '{print $NF}' | awk -F '.' '{print $1}')
else
usage
exit 1
fi
fi
# exit if name contains a space
case ${name} in
*\ * )
logger -s "Invalid hostname '${name}' ...Exiting"
exit
;;
esac
# if you want computers with a hostname that starts with 'dhcp' in AD
# comment the following block of code.
if [[ $name == dhcp* ]]
then
logger -s "not updating DNS record in AD, invalid name"
exit 0
fi
## update ##
case "${action}" in
add)
_KERBEROS
count=0
# does host have an existing 'A' record ?
A_REC=$($SAMBATOOL dns query "${Server}" "${domain}" "${name}" $AorAAAA "$KTYPE" 2>/dev/null | grep "$AorAAAA:" | awk '{print $2}')
# turn A_REC into an array
A_REC=("$A_REC")
if [ "${#A_REC[@]}" -eq 0 ]
then
# no A record to delete
result1=0
$SAMBATOOL dns add "${Server}" "${domain}" "${name}" $AorAAAA "${ip}" "$KTYPE"
result2="$?"
elif [ "${#A_REC[@]}" -gt 1 ]
then
for i in "${A_REC[@]}"
do
$SAMBATOOL dns delete "${Server}" "${domain}" "${name}" $AorAAAA "${i}" "$KTYPE"
done
# all A records deleted
result1=0
$SAMBATOOL dns add "${Server}" "${domain}" "${name}" $AorAAAA "${ip}" "$KTYPE"
result2="$?"
elif [ "${#A_REC[@]}" -eq 1 ]
then
# turn array into a variable
VAR_A_REC="${A_REC[*]}"
if [ "$VAR_A_REC" = "${ip}" ]
then
# Correct A record exists, do nothing
logger -s "Correct '$AorAAAA' record exists, not updating."
result1=0
result2=0
count=$((count+1))
elif [ "$VAR_A_REC" != "${ip}" ]
then
# Wrong A record exists
logger -s "'$AorAAAA' record changed, updating record."
$SAMBATOOL dns delete "${Server}" "${domain}" "${name}" $AorAAAA "${VAR_A_REC}" "$KTYPE"
result1="$?"
$SAMBATOOL dns add "${Server}" "${domain}" "${name}" $AorAAAA "${ip}" "$KTYPE"
result2="$?"
fi
fi
# get existing reverse zones (if any)
ReverseZones=$($SAMBATOOL dns zonelist "${Server}" "$KTYPE" --reverse | grep 'pszZoneName' | awk '{print $NF}')
if [ -z "$ReverseZones" ]; then
logger -s "No reverse zone found, not updating"
result3='0'
result4='0'
count=$((count+1))
else
for revzone in $ReverseZones
do
rev_zone_info "$revzone" "${ip}" "${AorAAAA}"
if [[ ${ip} = $ZoneIP* ]] && [ "$ZoneIP" = "$RZIP" ]
then
# does host have an existing 'PTR' record ?
PTR_REC=$($SAMBATOOL dns query "${Server}" "${revzone}" "${IP2add}" PTR "$KTYPE" 2>/dev/null | grep 'PTR:' | awk '{print $2}' | awk -F '.' '{print $1}')
if [[ -z $PTR_REC ]]
then
# no PTR record to delete
result3=0
$SAMBATOOL dns add "${Server}" "${revzone}" "${IP2add}" PTR "${name}"."${domain}" "$KTYPE"
result4="$?"
break
elif [ "$PTR_REC" = "${name}" ]
then
# Correct PTR record exists, do nothing
logger -s "Correct 'PTR' record exists, not updating."
result3=0
result4=0
count=$((count+1))
break
elif [ "$PTR_REC" != "${name}" ]
then
# Wrong PTR record exists
# points to wrong host
logger -s "'PTR' record changed, updating record."
$SAMBATOOL dns delete "${Server}" "${revzone}" "${IP2add}" PTR "${PTR_REC}"."${domain}" "$KTYPE"
result3="$?"
$SAMBATOOL dns add "${Server}" "${revzone}" "${IP2add}" PTR "${name}"."${domain}" "$KTYPE"
result4="$?"
break
fi
else
continue
fi
done
fi
;;
delete)
_KERBEROS
count=0
name=$(host -t PTR "${ip}" | sed 's/.\+pointer \([^.]\+\).\+$/\1/')
$SAMBATOOL dns delete "${Server}" "${domain}" "${name}" $AorAAAA "${ip}" "$KTYPE"
result1="$?"
# get existing reverse zones (if any)
ReverseZones=$($SAMBATOOL dns zonelist "${Server}" --reverse "$KTYPE" | grep 'pszZoneName' | awk '{print $NF}')
if [ -z "$ReverseZones" ]
then
logger -s "No reverse zone found, not updating"
result2='0'
count=$((count+1))
else
for revzone in $ReverseZones
do
rev_zone_info "$revzone" "${ip}" "${AorAAAA}"
if [[ ${ip} = $ZoneIP* ]] && [ "$ZoneIP" = "$RZIP" ]
then
host -t PTR "${ip}" > /dev/null 2>&1
ret="$?"
if [ $ret -eq 0 ]
then
$SAMBATOOL dns delete "${Server}" "${revzone}" "${IP2add}" PTR "${name}"."${domain}" "$KTYPE"
result2="$?"
else
result2='0'
count=$((count+1))
fi
break
else
continue
fi
done
fi
result3='0'
result4='0'
;;
*)
logger -s "Invalid action specified"
exit 103
;;
esac
result="${result1}:${result2}:${result3}:${result4}"
if [ "$count" -eq 0 ]
then
if [ "${result}" != "0:0:0:0" ]
then
logger -s "DHCP-DNS $action failed: ${result}"
exit 1
else
logger -s "DHCP-DNS $action succeeded"
fi
fi
if [ "$Add_macAddress" != 'no' ]
then
if [ -n "$DHCID" ]
then
Computer_Object=$(ldbsearch "$KTYPE" -H ldap://"$Server" "(&(objectclass=computer)(objectclass=ieee802Device)(cn=$name))" | grep -v '#' | grep -v 'ref:')
if [ -z "$Computer_Object" ]
then
# Computer object not found with the 'ieee802Device' objectclass, does the computer actually exist, it should.
Computer_Object=$(ldbsearch "$KTYPE" -H ldap://"$Server" "(&(objectclass=computer)(cn=$name))" | grep -v '#' | grep -v 'ref:')
if [ -z "$Computer_Object" ]
then
logger -s "Computer '$name' not found. Exiting."
exit 68
else
DN=$(echo "$Computer_Object" | grep 'dn:')
objldif="$DN
changetype: modify
add: objectclass
objectclass: ieee802Device"
attrldif="$DN
changetype: modify
add: macAddress
macAddress: $DHCID"
# add the ldif
echo "$objldif" | ldbmodify "$KTYPE" -H ldap://"$Server"
ret="$?"
if [ $ret -ne 0 ]
then
logger -s "Error modifying Computer objectclass $name in AD."
exit "${ret}"
fi
sleep 2
echo "$attrldif" | ldbmodify "$KTYPE" -H ldap://"$Server"
ret="$?"
if [ "$ret" -ne 0 ]; then
logger -s "Error modifying Computer attribute $name in AD."
exit "${ret}"
fi
unset objldif
unset attrldif
logger -s "Successfully modified Computer $name in AD"
fi
else
DN=$(echo "$Computer_Object" | grep 'dn:')
attrldif="$DN
changetype: modify
replace: macAddress
macAddress: $DHCID"
echo "$attrldif" | ldbmodify "$KTYPE" -H ldap://"$Server"
ret="$?"
if [ "$ret" -ne 0 ]
then
logger -s "Error modifying Computer attribute $name in AD."
exit "${ret}"
fi
unset attrldif
logger -s "Successfully modified Computer $name in AD"
fi
fi
fi
exit 0

44
docker-compose.yml Normal file
View File

@ -0,0 +1,44 @@
version: "3.9"
services:
dhcp4:
build:
context: ./
dockerfile: DockerfileIPv4
image: dhcp4:1.0.0
container_name: dhcp4
restart: "unless-stopped"
environment:
TZ: Asia/Tokyo
DHCPIF: "ens33"
DHCPSERVER: "addc"
DHCPDOMAIN: "example.net"
DHCPDNSADM: "ssoauth"
DHCPDBGFLG: "false"
hostname: dhcp4
network_mode: "host"
volumes:
- v4:/var/lib/dhcp
dhcp6:
build:
context: ./
dockerfile: DockerfileIPv6
image: dhcp6:1.0.0
container_name: dhcp6
restart: "unless-stopped"
environment:
TZ: Asia/Tokyo
DHCPIF: "ens33"
DHCPSERVER: "addc"
DHCPDOMAIN: "example.net"
DHCPDNSADM: "ssoauth"
DHCPDBGFLG: "false"
hostname: dhcp6
network_mode: "host"
volumes:
- v6:/var/lib/dhcp
volumes:
v4:
v6:

14
krb5.conf Normal file
View File

@ -0,0 +1,14 @@
[libdefaults]
default_realm = EXAMPLE.NET
dns_lookup_realm = false
dns_lookup_kdc = true
[realms]
EXAMPLE.NET = {
kdc = addc.example.net
# kdc = addc2.example.net
default_domain = example.net
}
[domain_realm]
addc = EXAMPLE.NET

2
setufw.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
ufw $1 allow to any port 547 proto udp from any comment "DHCPv6"

75
v4/dhcpd.conf Normal file
View File

@ -0,0 +1,75 @@
#-------------------------------
# Global options
#-------------------------------
authoritative;
option domain-name "example.net";
option domain-name-servers 192.168.110.10;
option routers 192.168.110.10;
default-lease-time 86400; # 24 hours.
max-lease-time 604800; # 7 days.
lease-file-name "/var/lib/dhcp/dhcpd.leases";
#-------------------------------
# Subnet
#-------------------------------
subnet 192.168.110.0 netmask 255.255.255.0 {
range 192.168.110.100 192.168.110.199;
}
#-------------------------------
# Fixed address
#-------------------------------
host party {
hardware ethernet 00:0C:29:14:6E:24;
fixed-address 192.168.110.12;
}
host work {
hardware ethernet 00:0c:29:0a:83:af;
fixed-address 192.168.110.3;
}
#-------------------------------
# Dynamic DNS
#-------------------------------
on commit {
set noname = concat("dhcp-", binary-to-ascii(10, 8, "-", leased-address));
set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
set ClientDHCID = concat (
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2)
);
set ClientName = pick-first-value(option host-name, config-option host-name, client-name, noname);
#log(concat("Commit: IP: ", ClientIP, " DHCID: ", ClientDHCID, " Name: ", ClientName));
execute("/usr/local/bin/dhcp-dyndns.sh", "add", ClientIP, ClientDHCID, ClientName);
}
on release {
set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
set ClientDHCID = concat (
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,1,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,2,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,3,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,4,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,5,1))),2), ":",
suffix (concat ("0", binary-to-ascii (16, 8, "", substring(hardware,6,1))),2)
);
#log(concat("Release: IP: ", ClientIP));
execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, ClientDHCID);
}
on expiry {
set ClientIP = binary-to-ascii(10, 8, ".", leased-address);
# cannot get a ClientMac here, apparently this only works when actually receiving a packet
#log(concat("Expired: IP: ", ClientIP));
# cannot get a ClientName here, for some reason that always fails
# however the dhcp update script will obtain the short hostname.
execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, "", "0");
}

23
v4/entrypoint.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
echo "Start container with parameter : $@"
trap sig_term SIGTERM
sig_term() {
echo "CATCH SIGTERM"
pkill -SIGTERM dhcpd
wait
exit 0
}
# Execute paramater.
exec "$@"
if [ ${DHCPDBGFLG^^} = "TRUE" ]; then
DBG="-d"
fi
dhcpd -4 $DBG -f $DHCPIF &
wait
exit 1

51
v6/dhcpd.conf Normal file
View File

@ -0,0 +1,51 @@
#-------------------------------
# Global options
#-------------------------------
authoritative;
option dhcp6.domain-search "example.net";
option dhcp6.name-servers fdaa:aaaa:aaaa:aaaa::10;
default-lease-time 86400; # 24 hours.
max-lease-time 604800; # 7 days.
lease-file-name "/var/lib/dhcp/dhcpd.leases";
#log-facility syslog;
#-------------------------------
# Subnet
#-------------------------------
subnet6 fdaa:aaaa:aaaa:aaaa::/64 {
range6 fdaa:aaaa:aaaa:aaaa::1:0100 fdaa:aaaa:aaaa:aaaa::1:0199;
}
#-------------------------------
# Fixed address
#-------------------------------
host party {
host-identifier option dhcp6.client-id 00:03:00:01:00:0c:29:14:6e:24;
fixed-address6 fdaa:aaaa:aaaa:aaaa::12;
on commit { execute("/usr/local/bin/dhcp-dyndns.sh", "add", "fdaa:aaaa:aaaa:aaaa::12", "no", "party", "-IPv6-"); }
on release { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", "fdaa:aaaa:aaaa:aaaa::12", "no", "party", "-IPv6-"); }
on expiry { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", "fdaa:aaaa:aaaa:aaaa::12", "no", "party", "-IPv6-"); }
}
host work {
host-identifier option dhcp6.client-id 00:03:00:01:00:0c:29:0a:83:af;
fixed-address6 fdaa:aaaa:aaaa:aaaa::3;
on commit { execute("/usr/local/bin/dhcp-dyndns.sh", "add", "fdaa:aaaa:aaaa:aaaa::3", "no", "work", "-IPv6-"); }
on release { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", "fdaa:aaaa:aaaa:aaaa::3", "no", "work", "-IPv6-"); }
on expiry { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", "fdaa:aaaa:aaaa:aaaa::3", "no", "work", "-IPv6-"); }
}
#-------------------------------
# Dynamic DNS
#-------------------------------
on commit {
set ClientIP = binary-to-ascii(16, 16, ":", substring(option dhcp6.ia-na, 16, 16));
set ClientName = option fqdn.hostname;
execute("/usr/local/bin/dhcp-dyndns.sh", "add", ClientIP, "no", ClientName, "-IPv6-");
}
on release { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, "no", ClientName, "-IPv6-"); }
on expiry { execute("/usr/local/bin/dhcp-dyndns.sh", "delete", ClientIP, "no", ClientName, "-IPv6-"); }

24
v6/entrypoint.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
echo "Start container with parameter : $@"
trap sig_term SIGTERM
sig_term() {
echo "CATCH SIGTERM"
pkill -SIGTERM dhcpd
pkill -SIGTERM radvd
wait
exit 0
}
# Execute paramater.
exec "$@"
if [ ${DHCPDBGFLG^^} = "TRUE" ]; then
DBG=-d
fi
dhcpd -6 $DBG -f $DHCPIF &
radvd -n &
wait

16
v6/radvd.conf Normal file
View File

@ -0,0 +1,16 @@
interface ens33
{
AdvSendAdvert on;
AdvManagedFlag on;
AdvOtherConfigFlag on;
AdvDefaultPreference low;
prefix fdaa:aaaa:aaaa:aaaa::/64
{
AdvAutonomous off;
};
AdvCurHopLimit 0;
};