CA SUDO 自动化部署

发布时间 2023-04-07 16:21:57作者: ——浮生——

实现私有CA

centos7实现证书申请

[root@centos7 certs]# pwd
/etc/pki/tls/certs
[root@centos7 certs]# make app.crt
umask 77 ; \
/usr/bin/openssl genrsa -aes128 2048 > app.key
Generating RSA private key, 2048 bit long modulus
............................................................+++
...........................................................+++
e is 65537 (0x10001)
Enter pass phrase:
140632010667920:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:831:You must type in 4 to 1023 characters
Enter pass phrase:
Verifying - Enter pass phrase:
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key app.key -x509 -days 365 -out app.crt 
Enter pass phrase for app.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:hn
Locality Name (eg, city) [Default City]:zz
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:app.magedu.org
Email Address []:
[root@centos7 certs]# ll
total 20
-rw-------  1 root root 1294 Jun 24 22:11 app.crt
-rw-------  1 root root 1766 Jun 24 22:10 app.key
lrwxrwxrwx. 1 root root   49 Jan 19 12:09 ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
lrwxrwxrwx. 1 root root   55 Jan 19 12:09 ca-bundle.trust.crt -> /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt
-rwxr-xr-x. 1 root root  610 Aug  9  2019 make-dummy-cert
-rw-r--r--. 1 root root 2516 Aug  9  2019 Makefile
-rwxr-xr-x. 1 root root  829 Aug  9  2019 renew-dummy-cert

centos8 实现证书申请

[root@localhost ~]# mkdir -pv /etc/pki/CA/{certs,crl,newcerts,private}
[root@localhost ~]# touch CA/index.txt
[root@localhost ~]# echo 0F > /etc/pki/CA/serial
[root@localhost CA]# openssl genrsa -out private/cakey.pem 2048
[root@localhost CA]# openssl req -new -x509 -key private/cakey.pem -days 365 -out cacert.pem

[root@localhost ~]# openssl genrsa -out /data/app/app.key 2048
[root@localhost ~]# openssl req -new -key /data/app/app.key -out /data/app/app.csr
[root@localhost ~]# openssl ca -in /data/app/app.csr -out certs/app.crt

[root@localhost ~]# cp certs/app.crt /data/app/

[root@localhost CA]# ll /data/app/
total 16
-rw-r--r-- 1 root root 4391 Jun 24 19:35 app.crt
-rw-r--r-- 1 root root  980 Jun 24 19:33 app.csr
-rw------- 1 root root 1675 Jun 24 19:32 app.key

ca申请脚本
[root@localhost script]# cat create_ca.sh
#!/bin/bash
#实现简单脚本申请证书
#ca证书subj信息
ca_subject="/C=CN/ST=hn/L=zhengzhou/O=magedu/CN=ca.magedu.org"
#证书申请subj信息
subject="/C=CN/ST=hn/L=zhengzhou/O=magedu/CN=app.liwenliang.org"
#证书编号
serial="11"
#证书有效期
exprie="365"
key_size="2048"
#创建ca自签名证书
create_ca(){
	openssl genrsa -out /etc/pki/CA/private/cakey.pem ${key_size}
	openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days ${exprie} -out /etc/pki/CA/cacert.pem -subj ${ca_subject}
}
#创建app证书
create_app(){
	openssl genrsa -out /data/app/app.key ${key_size}
	openssl req -new -key /data/app/app.key -out /data/app/app.csr -subj ${subject}
	openssl ca -in /data/app/app.csr -out /etc/pki/CA/certs/app.crt -days ${exprie}
    cp /etc/pki/CA/certs/app.crt /data/app/
}
PS3="请选择(1-3) ps:请确认index.txt serial文件存在,如过不存在请输入4"
select num in "1 create ca","2 create app","3 end";do
	case ${REPLY} in
		1)
			create_ca
			;;
		2)
			create_app
			;;
		3)
			echo "create over"
			break
			;;
		4)
			touch /etc/pki/CA/index.txt
			echo 0F > /etc/pki/CA/serial
			;;
	esac
done

注:为安全考虑,建议修改私钥权限600

SSH服务

ssh: secure shell protocol, 22/tcp, 安全的远程登录,实现加密通信,代替传统的 telnet 协议

公钥交换:

​ 客户端发起链接请求
​ 服务端返回自己的公钥,以及一个会话ID,客户端得到服务端公钥
​ 客户端生成密钥对
​ 客户端用自己的公钥异或会话ID,通过异或计算出一个值Res,并用服务端的公钥加密
​ 客户端发送加密后的值到服务端,服务端用私钥解密,得到Res
​ 服务端用解密后的值Res异或会话ID,计算出客户端的公钥,服务端得到客户端公钥
​ 最终:双方各自持有三个秘钥,分别为自己的一对公、私钥,以及对方的公钥,之后的所有通讯都 会被加密
​ 注:异或:A^B=C C^A=B C^B=A

加密通信

​ 客户端和服务端各自拥有一对密钥和对方的公钥,通讯过程中使用对方公钥加密对话,接收方使用密钥解密,实现对话加密

基于key验证

创建key
[root@centos7 data]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:c5Hz1Smz05YcXzmG565Cbo1ZgU7bKRdvxelBjtD0w6w root@centos7.example.com
The key's randomart image is:
+---[RSA 2048]----+
|            o.   |
|           o .=oo|
|          + o+=&+|
|           * =@+X|
|        S + +E**+|
|         o = =++ |
|          o B .. |
|           * ..  |
|          . ..   |
+----[SHA256]-----+

将key复制到目标机器
[root@centos7 data]# ssh-copy-id root@10.0.0.8
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@10.0.0.8's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@10.0.0.8'"
and check to make sure that only the key(s) you wanted were added.

[root@centos7 data]# ssh 10.0.0.8
Last login: Fri Jun 24 19:37:00 2022 from 10.0.0.1
[root@localhost ~]# hostname -I
10.0.0.8


实现多机器基于key验证
[root@centos7 .ssh]# ssh-keygen  -P ""  -f /root/.ssh/id_rsa #-p指定加密密码  -f指定保存文件
[root@centos7 .ssh]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:gFn4gk1OsaSh3plMaKdcBVO1oEMhYEYhyIF4D591CsA root@centos7.example.com
The key's randomart image is:
+---[RSA 2048]----+
|XO=***o.         |
|BoE+O=o o        |
|.+./+=.+         |
|+ O @ o.         |
| + = .  S        |
|                 |
|                 |
|                 |
|                 |
+----[SHA256]-----+
[root@centos7 .ssh]# ll
total 8
-rw------- 1 root root 1675 Jun 24 22:55 id_rsa
-rw-r--r-- 1 root root  406 Jun 24 22:55 id_rsa.pub
[root@centos7 .ssh]# ssh-copy-id 127.0.0.1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:wKI9CiPn+WIQ6qAPaHU0rpi0b8DcLUhdtNfsAW0eZN4.
ECDSA key fingerprint is MD5:71:eb:d0:10:2c:69:3f:4c:0c:6f:87:77:f3:0c:45:e4.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@127.0.0.1's password: 
Permission denied, please try again.
root@127.0.0.1's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '127.0.0.1'"
and check to make sure that only the key(s) you wanted were added.

[root@centos7 .ssh]# scp -r /root/.ssh root@10.0.0.8:/root/
id_rsa                                                                                                                                                   100% 1675     1.4MB/s   00:00    
id_rsa.pub                                                                                                                                               100%  406   297.4KB/s   00:00    
known_hosts                                                                                                                                              100%  341   373.7KB/s   00:00    
authorized_keys                                                                                                                                          100%  406   499.5KB/s   00:00    

ssh可在后面跟命令是现在远程主机上执行
[root@centos7 data]# ssh 10.0.0.8 hostname -I
10.0.0.8 
[root@centos7 data]# ssh 10.0.0.8 <ip_ping.sh 
[root@centos7 data]# ssh 10.0.0.8 cat /data/ip.txt
10.0.0.17


scp命令可将文件拷贝到远程主机 -r 递归  -p保留原属性
[root@centos7 .ssh]# scp -r /root/.ssh root@10.0.0.8:/root/
id_rsa                                                                                                                                                   100% 1675     1.4MB/s   00:00    
id_rsa.pub                                                                                                                                               100%  406   297.4KB/s   00:00    
known_hosts                                                                                                                                              100%  341   373.7KB/s   00:00    
authorized_keys

rsync工具可以基于ssh和rsync协议实现高效率的远程系统之间复制文件,使用安全的shell连接做为传输方式,比scp更快,基于增量数据同步,即只复制两方不同的文件,此工具来自于rsync包
注:通信两端主机都需要安装 rsync 软件

格式:
rsync  -av /etc server1:/tmp #复制目录和目录下文件
rsync  -av /etc/ server1:/tmp #只复制目录下文件
常用选项:
-n 模拟复制过程
-v 显示详细过程
-r 递归复制目录树
-p 保留权限
-t 保留修改时间戳
-g 保留组信息
-o 保留所有者信息
-l 将软链接文件本身进行复制(默认)
-L 将软链接文件指向的文件复制
-u 如果接收者的文件比发送者的文件较新,将忽略同步
-z 压缩,节约网络带宽
-a 存档,相当于-rlptgoD,但不保留ACL(-A)和SELinux属性(-X)
--delete 源数据删除,目标数据也自动同步删除

[root@centos7 data]# rsync -av /data/ 10.0.0.8:/data
sending incremental file list
./
ip.txt
ip_ping.sh

sent 339 bytes  received 63 bytes  804.00 bytes/sec
total size is 159  speedup is 0.40
[root@centos7 data]# rsync -av /data/ 10.0.0.8:/data
sending incremental file list
./
ip.txt
ip_ping.sh

sent 339 bytes  received 57 bytes  792.00 bytes/sec
total size is 159  speedup is 0.40

[root@localhost data]# ll
total 8
-rw-r--r-- 1 root root 150 Jun 24 23:03 ip_ping.sh
-rw-r--r-- 1 root root   9 Jun 24 23:03 ip.txt

sshd常用参数配置

[root@localhost data]# cat  /etc/ssh/sshd_config
Port        #生产建议修改
ListenAddress ip
LoginGraceTime 2m
PermitRootLogin yes #默认ubuntu不允许root远程ssh登录
StrictModes yes   #检查.ssh/文件的所有者,权限等
MaxAuthTries   6     #pecifies the maximum number of authentication 
attempts permitted per connection. Once the number of failures reaches half this 
value, additional failures are logged. The default is 6.
MaxSessions  10         #同一个连接最大会话
PubkeyAuthentication yes     #基于key验证
PermitEmptyPasswords no      #空密码连接
PasswordAuthentication yes   #基于用户名和密码连接
GatewayPorts no
ClientAliveInterval 10 #单位:秒
ClientAliveCountMax 3 #默认3
UseDNS yes #提高速度可改为no
GSSAPIAuthentication yes #提高速度可改为no
MaxStartups    #未认证连接最大值,默认值10
Banner /path/file
#以下可以限制可登录用户的办法:
AllowUsers user1 user2 user3
DenyUsers user1 user2 user3
AllowGroups g1 g2
DenyGroups g1 g2

sshpass工具

​ sshpass用于非 交互SSH的密码验证

-p password #后跟密码它允许你用 -p 参数指定明文密码,然后直接登录远程服务器
-f filename #后跟保存密码的文件名,密码是文件内容的第一行
-e #将环境变量SSHPASS作为密码

[root@centos7 data]# sshpass -p '123456' ssh -o  StrictHostKeyChecking=no 10.0.0.8 hostname -I
10.0.0.8

实现批量key验证
#!/bin/bash
ip=10.0.0
ssh-keygen  -P ""  -f /root/.ssh/id_rsa  >/dev/null
for i in {1..10}
do
        ping -c1 -W1 ${ip}.$i >/dev/null && sshpass -p '123456' ssh-copy-id  -o  StrictHostKeyChecking=no -o ConnectTimeout=1 ${ip}.$i >/dev/null &
done
wait

StrictHostKeyChecking=no  跳过首次验证检测
ConnectTimeout=1 连接超时时间

sudo权限委派

sudo 即superuser do,允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt, reboot,su等等。这样不仅减少了root用户的登录 和管理时间,同样也提高了安全性

sudo特性:

​ sudo能够授权指定用户在指定主机上运行某些命令。如果未授权用户尝试使用 sudo,会提示联系 管理员

​ sudo提供了丰富的日志,详细地记录了每个用户干了什么。它能够将日志传到中心主机或者日志服 务器

​ sudo使用时间戳文件来执行类似的“检票”系统。当用户调用sudo并且输入它的密码时,用户获得 了一张存活期为5分钟的票

​ sudo的配置文件是sudoers文件,它允许系统管理员集中的管理用户的使用权限和使用的主机。它 所存放的位置默认是在/etc/sudoers,属性必须为0440

包:sudo

配置文件:/etc/sudo.conf

授权规则配置文件:

	/etc/sudoers 
	/etc/sudoers.d 

安全编辑授权规则文件和语法检查工具

	/usr/sbin/visudo

#检查语法

	visudo -c 

#检查指定配置文件语法

	visudo -f /etc/sudoers.d/test 

授权编辑规则文件的工具:/usr/bin/sudoedit

执行授权命令:/usr/bin/sudo

时间戳文件:/var/db/sudo

日志文件:/var/log/secure

sudo命令

	ls -l /usr/bin/sudo 
	sudo -i -u wang 切换身份功能和 su 相似,但不一样,sudo必须提前授权,而且要输入自已的密码 
	sudo [-u user] COMMAND 
		-V 显示版本信息等配置信息 
		-u user 默认为root -l,ll 列出用户在主机上可用的和被禁止的命令 
		-v 再延长密码有效期限5分钟,更新时间戳
		-k 清除时间戳(1970-01-01),下次需要重新输密码 
		-K 与-k类似,还要删除时间戳文件 
		-b 在后台执行指令 
		-p 改变询问密码的提示符号 
		示例:-p "password on %h for user %p: " 

配置文件格式说明:/etc/sudoers, /etc/sudoers.d/

配置文件中支持使用通配符 glob

    ? 任意单一字符 
    \* 匹配任意长度字符 
    [wxc] 匹配其中一个字符 
    [!wxc] 除了这三个字符的其它字符 
    \x 转义 
    [[alpha]] 字母 
    /bin/ls [[alpha]]*

sudoers 授权规则格式:

用户  登入主机=(代表用户)  命令 
user host=(runas)      command
    root ALL=(ALL) ALL
    user: 运行命令者的身份 
    host: 通过哪些主机 (
    runas):以哪个用户的身份 
    command: 运行哪些命令

sudoers的别名

User和runas:
 username
 	\#uid 
    %group_name 
    %#gid 
    user_alias|runas_alias 
 host: 
    ip或hostname 
    network(/netmask) 
    host_alias 
 command: 
    command name 
    directory 
    sudoedit 
    Cmnd_Alias 
 sudo别名有四种类型: 
    User_Alias 
    Runas_Alias
    Host_Alias 
    Cmnd_Alias

别名格式:

	[A-Z]([A-Z][0-9]_)*

别名定义:

	Alias_Type NAME1 = item1,item2,item3 : NAME2 = item4, item5 
范例:
chen    10.0.0.17=(root) /bin/cat,/sbin/ip
[root@centos7 data]# visudo -c
/etc/sudoers: parsed OK

User_Alias SYSUSER = chen
Cmnd_Alias CMD = /usr/sbin/ip,/usr/sbin/ifconfig
SYSUSER ALL=(root) CMD
[root@centos7 data]# visudo -c
/etc/sudoers: parsed OK

时间同步

加密和安全当前都离不开时间的同步,否则各种网络服务可能不能正常运行
时间同步服务
多主机协作工作时,各个主机的时间同步很重要,时间不一致会造成很多重要应用的故障,如:加密协 议,日志,集群等, 利用NTP(Network Time Protocol) 协议使网络中的各个计算机时间达到同步。 目前NTP协议属于运维基础架构中必备的基本服务之一
时间同步软件实现:
ntp
chrony

配置文件

[root@localhost data]# cat /etc/chrony.conf
server  #可用于时钟服务器,iburst 选项当服务器可达时,发送一个八个数据包而不是通常的一个数据
包。 包间隔通常为2秒,可加快初始同步速度
pool     #该指令的语法与server 指令的语法相似,不同之处在于它用于指定NTP服务器池而不是单个
NTP服务器。池名称应解析为随时间可能会变化的多个地址
driftfile #根据实际时间计算出计算机增减时间的比率,将它记录到一个文件中,会在重启后为系统时钟作
出补偿
rtcsync  #启用内核模式,系统时间每11分钟会拷贝到实时时钟(RTC)
allow / deny #指定一台主机、子网,或者网络以允许或拒绝访问本服务器
cmdallow / cmddeny #可以指定哪台主机可以通过chronyd使用控制命令
bindcmdaddress #允许chronyd监听哪个接口来接收由chronyc执行的命令
makestep # 通常chronyd将根据需求通过减慢或加速时钟,使得系统逐步纠正所有时间偏差。在某些特定
情况下,系统时钟可能会漂移过快,导致该调整过程消耗很长的时间来纠正系统时钟。该指令强制chronyd在
调整期大于某个阀值时调整系统时钟
local stratum 10  #即使server指令中时间服务器不可用,也允许将本地时间作为标准时间授时给其它
客户端

实现时间同步

添加时间服务器
[root@localhost data]# cat /etc/chrony.conf 
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
#pool 2.centos.pool.ntp.org iburst
server ntp1.aliyun.com
server ntp2.aliyun.com
server ntp3.aliyun.com
重启服务
[root@localhost data]# systemctl restart chronyd
查看同步信息
[root@localhost data]# chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^- 120.25.115.20                 2   6    13    38  +2620us[+2620us] +/-   17ms
^* 203.107.6.88                  2   6    17    38   +369us[ +123us] +/-   20ms


实现私有时间服务器
[root@localhost data]# vim /etc/chrony.conf 
# Allow NTP client access from local network.
allow 10.0.0.17/24
#0.0.0.0/0 允许全网段
# Serve time even if not synchronized to a time source.
local stratum 10
重启服务查看端口,
[root@localhost data]# systemctl restart chronyd.service
[root@localhost data]# ss -anu
UNCONN                   0                        0                                                0.0.0.0:123                                           0.0.0.0:*
客户端添加服务器
[root@centos7 data]# vim /etc/chrony.conf
server 10.0.0.8 iburst

[root@centos7 data]# chronyc sources -v
210 Number of sources = 1

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current synced, '+' = combined , '-' = not combined,
| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* 10.0.0.8                      3   6    17    17  -4616ns[ -142us] +/-   22ms

PAM认证机制

认证库:文本文件,MySQL,NIS,LDAP等

PAM:Pluggable Authentication Modules,插件式的验证模块,

PAM 只关注如何为服务验证用户的 API,通过提供一些动态链接库和一套统一的 API,将系统提供的服务和该服务的认证方式分开,使得系统管理员可以灵活地根据需要给不同的服务配 置不同的认证方式而无需更改服务程序一种认证框架,自身不做认证

PAM实现资源访问限制

[root@centos7 app]# cat /etc/security/limits.conf
apache  - nofile 10240
chen   hard nproc 3
chen   - maxlogins 2
[root@centos7 ~]# su chen
[chen@centos7 root]$ bash
bash: fork: retry: No child processes

生产案例:
vim /etc/security/limits.conf  
*    -   core       unlimited
*    -   nproc       1000000
*    -   nofile      1000000
*    -   memlock     32000
*    -   msgqueue    8192000

自动化部署

Linux的安装过程如下:
加载boot loader
加载启动安装菜单
加载内核和initrd文件
加载根系统
运行anaconda的安装向导

一键pxe

#!/bin/bash
yum -y install httpd tftp-server dhcp syslinux system-config kickstart
mkdir -pv /var/www/html/centos/7/os/x86_64
mount /dev/sr0 /var/www/html/centos/7/os/x86_64

mkdir /var/www/html/ks/
cat > /var/www/html/ks/centos7.cfg <<EOF
install
xconfig  --startxonboot
keyboard --vckeymap=us --xlayouts='us'
rootpw --iscrypted $1$bpNEv8S5$lK.CjNkf.YCpFPHskSNiN0
url --url="http://10.0.0.17/centos/7/os/x86_64"
lang en_US
auth  --useshadow  --passalgo=sha512
text
firstboot --enable
selinux --disabled
skipx
services --disabled="chronyd"
ignoredisk --only-use=sda
firewall --disabled
network  --bootproto=dhcp --device=eth0
network  --hostname=centos7.magedu.org
reboot
timezone Asia/Shanghai --nontp
bootloader --append="net.ifnames=0" --location=mbr --boot-drive=sda
zerombr
#autopart --type=lvm
clearpart --all --initlabel
part swap --fstype="swap" --ondisk=sda --size=3072
part / --fstype="xfs" --ondisk=sda --size=51200
part /boot --fstype="xfs" --ondisk=sda --size=1024
part /data --fstype="xfs" --ondisk=sda --size=30720
%post
useradd wang
%end
%packages
@core
%end
EOF
cat > /etc/dhcp/dhcpd.conf <<EOF
option domain-name "example.com";
default-lease-time 600;
max-lease-time 7200;
subnet 10.0.0.0 netmask 255.255.255.0 {
 range 10.0.0.1 10.0.0.200;
 option routers 10.0.0.1;
 next-server 10.0.0.17;
 filename "pxelinux.0";
}
EOF
mkdir /var/lib/tftpboot/pxelinux.cfg/
cp /usr/share/syslinux/{pxelinux.0,menu.c32} /var/lib/tftpboot/
cp /var/www/html/centos/7/os/x86_64/isolinux/{vmlinuz,initrd.img} /var/lib/tftpboot/
cat > /var/lib/tftpboot/pxelinux.cfg/default <<EOF
default menu.c32
timeout 600
menu title PXE INSTALL MENU
label auto
 menu default
 menu label ^Auto Install CentOS 7
 kernel vmlinuz
 append initrd=initrd.img ks=http://10.0.0.17/ks/centos7.cfg 
label manual
 menu label ^Manual Install CentOS 7
 kernel vmlinuz
 append initrd=initrd.img inst.repo=http://10.0.0.17/centos7/os/x86_64/
label local   
   menu label ^Boot from local drive
   localboot 0xffff
EOF
systemctl enable --now httpd tftp dhcpd