一、主节点配置

注意:以下所有命令和脚本都是在 centos7 环境运行。
主节点:用于其他所有机器

  1. # 在主节点安装 ansible 用于控制其他机器
  2. yun update && yun install python3 python3-pip && pip3 install --upgrade pip
  3. pip3 install ansible
  4. yum install sshpass -y
  5. export ANSIBLE_HOST_KEY_CHECKING=False # 屏蔽密码警告,需要设置
  6. export ANSIBLE_FORKS=3 # ansible 工作并发数,可以不设置

上面命令全部执行完毕且没有异常之后,开始简单配置 ansible。
新建文件:/etc/ansible/hosts

  1. [ssr] # 此处ssr只是个标签名字,后面会用到
  2. 54.169.168.254
  3. 54.169.111.130
  4. 13.228.203.107
  5. ... 被控制机器ip列表
  6. [all:vars]
  7. ansible_ssh_port=22 # 机器远程ssh连接端口,如果不知道默认就是22
  8. ansible_ssh_user=root # 机器连接用户名
  9. ansible_ssh_pass=Rzxxxxx # 机器连接密码

新建文件:/root/install-ssr-server.sh,改文件为ssr服务安装脚本
改脚本的第292行的41218是机器需要映射的端口,可以自行修改。
该脚本可以通过远程或者拷贝的方式新建,远程可使用:wget “https://github.com/h1code2/opt/raw/main/shell/install-ssr.sh“ -O install-ssr-server.sh 下载

  1. #!/bin/bash
  2. # shadowsocksR/SSR CentOS 7/8一键安装
  3. RED="\033[31m" # Error message
  4. GREEN="\033[32m" # Success message
  5. YELLOW="\033[33m" # Warning message
  6. BLUE="\033[36m" # Info message
  7. PLAIN='\033[0m'
  8. V6_PROXY=""
  9. IP=`curl -sL -4 ip.sb`
  10. if [[ "$?" != "0" ]]; then
  11. IP=`curl -sL -6 ip.sb`
  12. V6_PROXY="https://gh.hijk.art/"
  13. fi
  14. FILENAME="ShadowsocksR-v3.2.2"
  15. URL="${V6_PROXY}https://github.com/shadowsocksrr/shadowsocksr/archive/3.2.2.tar.gz"
  16. BASE=`pwd`
  17. OS=`hostnamectl | grep -i system | cut -d: -f2`
  18. CONFIG_FILE="/etc/shadowsocksR.json"
  19. colorEcho() {
  20. echo -e "${1}${@:2}${PLAIN}"
  21. }
  22. checkSystem() {
  23. result=$(id | awk '{print $1}')
  24. if [ $result != "uid=0(root)" ]; then
  25. colorEcho $RED " 请以root身份执行该脚本"
  26. exit 1
  27. fi
  28. if [ ! -f /etc/centos-release ];then
  29. res=`which yum`
  30. if [ "$?" != "0" ]; then
  31. colorEcho $RED " 系统不是CentOS"
  32. exit 1
  33. fi
  34. else
  35. result=`cat /etc/centos-release|grep -oE "[0-9.]+"`
  36. main=${result%%.*}
  37. if [ $main -lt 7 ]; then
  38. colorEcho $RED " 不受支持的CentOS版本"
  39. exit 1
  40. fi
  41. fi
  42. }
  43. slogon() {
  44. clear
  45. echo "#############################################################"
  46. echo -e "# ${RED} ShadowsocksR/SSR 一键安装脚本${PLAIN} #"
  47. echo "#############################################################"
  48. echo ""
  49. }
  50. getData() {
  51. read -p " 请设置SSR的密码(不输入则随机生成):" PASSWORD
  52. [ -z "$PASSWORD" ] && PASSWORD=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1`
  53. echo ""
  54. colorEcho $BLUE " 密码: $PASSWORD"
  55. echo ""
  56. while true
  57. do
  58. read -p " 请设置SSR的端口号[1-65535]:" PORT
  59. [ -z "$PORT" ] && PORT="12345"
  60. if [ "${PORT:0:1}" = "0" ]; then
  61. echo -e " ${RED}端口不能以0开头${PLAIN}"
  62. exit 1
  63. fi
  64. expr $PORT + 0 &>/dev/null
  65. if [ $? -eq 0 ]; then
  66. if [ $PORT -ge 1 ] && [ $PORT -le 65535 ]; then
  67. echo ""
  68. colorEcho $BLUE " 端口号: $PORT"
  69. echo ""
  70. break
  71. else
  72. colorEcho $RED " 输入错误,端口号为1-65535的数字"
  73. fi
  74. else
  75. colorEcho $RED " 输入错误,端口号为1-65535的数字"
  76. fi
  77. done
  78. colorEcho $BLUE " 请选择SSR的加密方式:"
  79. echo " 1)aes-256-cfb"
  80. echo " 2)aes-192-cfb"
  81. echo " 3)aes-128-cfb"
  82. echo " 4)aes-256-ctr"
  83. echo " 5)aes-192-ctr"
  84. echo " 6)aes-128-ctr"
  85. echo " 7)aes-256-cfb8"
  86. echo " 8)aes-192-cfb8"
  87. echo " 9)aes-128-cfb8"
  88. echo " 10)camellia-128-cfb"
  89. echo " 11)camellia-192-cfb"
  90. echo " 12)camellia-256-cfb"
  91. echo " 13)chacha20-ietf"
  92. read -p " 请选择加密方式(默认aes-256-cfb)" answer
  93. if [ -z "$answer" ]; then
  94. METHOD="aes-256-cfb"
  95. else
  96. case $answer in
  97. 1)
  98. METHOD="aes-256-cfb"
  99. ;;
  100. 2)
  101. METHOD="aes-192-cfb"
  102. ;;
  103. 3)
  104. METHOD="aes-128-cfb"
  105. ;;
  106. 4)
  107. METHOD="aes-256-ctr"
  108. ;;
  109. 5)
  110. METHOD="aes-192-ctr"
  111. ;;
  112. 6)
  113. METHOD="aes-128-ctr"
  114. ;;
  115. 7)
  116. METHOD="aes-256-cfb8"
  117. ;;
  118. 8)
  119. METHOD="aes-192-cfb8"
  120. ;;
  121. 9)
  122. METHOD="aes-128-cfb8"
  123. ;;
  124. 10)
  125. METHOD="camellia-128-cfb"
  126. ;;
  127. 11)
  128. METHOD="camellia-192-cfb"
  129. ;;
  130. 12)
  131. METHOD="camellia-256-cfb"
  132. ;;
  133. 13)
  134. METHOD="chacha20-ietf"
  135. ;;
  136. *)
  137. colorEcho $RED " 无效的选择,使用默认加密方式"
  138. METHOD="aes-256-cfb"
  139. esac
  140. fi
  141. echo ""
  142. colorEcho $BLUE " 加密方式: $METHOD"
  143. echo ""
  144. colorEcho $BLUE " 请选择SSR协议:"
  145. echo " 1)origin"
  146. echo " 2)verify_deflate"
  147. echo " 3)auth_sha1_v4"
  148. echo " 4)auth_aes128_md5"
  149. echo " 5)auth_aes128_sha1"
  150. echo " 6)auth_chain_a"
  151. echo " 7)auth_chain_b"
  152. echo " 8)auth_chain_c"
  153. echo " 9)auth_chain_d"
  154. echo " 10)auth_chain_e"
  155. echo " 11)auth_chain_f"
  156. read -p " 请选择SSR协议(默认origin)" answer
  157. if [ -z "$answer" ]; then
  158. PROTOCOL="origin"
  159. else
  160. case $answer in
  161. 1)
  162. PROTOCOL="origin"
  163. ;;
  164. 2)
  165. PROTOCOL="verify_deflate"
  166. ;;
  167. 3)
  168. PROTOCOL="auth_sha1_v4"
  169. ;;
  170. 4)
  171. PROTOCOL="auth_aes128_md5"
  172. ;;
  173. 5)
  174. PROTOCOL="auth_aes128_sha1"
  175. ;;
  176. 6)
  177. PROTOCOL="auth_chain_a"
  178. ;;
  179. 7)
  180. PROTOCOL="auth_chain_b"
  181. ;;
  182. 8)
  183. PROTOCOL="auth_chain_c"
  184. ;;
  185. 9)
  186. PROTOCOL="auth_chain_d"
  187. ;;
  188. 10)
  189. PROTOCOL="auth_chain_e"
  190. ;;
  191. 11)
  192. PROTOCOL="auth_chain_f"
  193. ;;
  194. *)
  195. colorEcho $RED " 无效的选择,使用默认协议"
  196. PROTOCOL="origin"
  197. esac
  198. fi
  199. echo ""
  200. colorEcho $BLUE " SSR协议: $PROTOCOL"
  201. echo ""
  202. colorEcho $BLUE " 请选择SSR混淆模式:"
  203. echo " 1)plain"
  204. echo " 2)http_simple"
  205. echo " 3)http_post"
  206. echo " 4)tls1.2_ticket_auth"
  207. echo " 5)tls1.2_ticket_fastauth"
  208. read -p " 请选择混淆模式(默认plain)" answer
  209. if [ -z "$answer" ]; then
  210. OBFS="plain"
  211. else
  212. case $answer in
  213. 1)
  214. OBFS="plain"
  215. ;;
  216. 2)
  217. OBFS="http_simple"
  218. ;;
  219. 3)
  220. OBFS="http_post"
  221. ;;
  222. 4)
  223. OBFS="tls1.2_ticket_auth"
  224. ;;
  225. 5)
  226. OBFS="tls1.2_ticket_fastauth"
  227. ;;
  228. *)
  229. colorEcho $RED " 无效的选择,使用默认混淆模式"
  230. OBFS="plain"
  231. esac
  232. fi
  233. echo ""
  234. colorEcho $BLUE " 混淆模式: $OBFS"
  235. echo ""
  236. }
  237. preinstall() {
  238. colorEcho $BLUE " 更新系统..."
  239. yum clean all
  240. #yum update -y
  241. colorEcho $BLUE " 安装必要软件"
  242. yum install -y epel-release telnet curl wget vim net-tools libsodium openssl unzip tar qrencode
  243. res=`which wget`
  244. [ "$?" != "0" ] && yum install -y wget
  245. res=`which netstat`
  246. [ "$?" != "0" ] && yum install -y net-tools
  247. if [ $main -eq 8 ]; then
  248. ln -s /usr/bin/python3 /usr/bin/python
  249. fi
  250. if [ -s /etc/selinux/config ] && grep 'SELINUX=enforcing' /etc/selinux/config; then
  251. sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
  252. setenforce 0
  253. fi
  254. }
  255. installSSR() {
  256. if [ ! -d /usr/local/shadowsocks ]; then
  257. echo 下载安装文件
  258. if ! wget --no-check-certificate -O ${FILENAME}.tar.gz ${URL}; then
  259. echo -e " [${RED}Error${PLAIN}] 下载文件失败!"
  260. exit 1
  261. fi
  262. tar -zxf ${FILENAME}.tar.gz
  263. mv shadowsocksr-3.2.2/shadowsocks /usr/local
  264. if [ ! -f /usr/local/shadowsocks/server.py ]; then
  265. colorEcho $RED " $OS 安装失败"
  266. cd ${BASE} && rm -rf shadowsocksr-3.2.2 ${FILENAME}.tar.gz
  267. exit 1
  268. fi
  269. cd ${BASE} && rm -rf shadowsocksr-3.2.2 ${FILENAME}.tar.gz
  270. fi
  271. PORT=41218
  272. PASSWORD="uzon57jd0v869t7w"
  273. METHOD="chacha20-ietf"
  274. PROTOCOL="auth_aes128_sha1"
  275. OBFS="plain"
  276. cat > $CONFIG_FILE<<-EOF
  277. {
  278. "server":"0.0.0.0",
  279. "server_ipv6":"::",
  280. "server_port":${PORT},
  281. "local_port":1080,
  282. "password":"${PASSWORD}",
  283. "timeout":600,
  284. "method":"${METHOD}",
  285. "protocol":"${PROTOCOL}",
  286. "protocol_param":"",
  287. "obfs":"${OBFS}",
  288. "obfs_param":"",
  289. "redirect":"",
  290. "dns_ipv6":false,
  291. "fast_open":false,
  292. "workers":1
  293. }
  294. EOF
  295. cat > /usr/lib/systemd/system/shadowsocksR.service <<-EOF
  296. [Unit]
  297. Description=shadowsocksR
  298. Documentation=https://hijk.art/
  299. After=network-online.target
  300. Wants=network-online.target
  301. [Service]
  302. Type=forking
  303. LimitNOFILE=32768
  304. ExecStart=/usr/local/shadowsocks/server.py -c $CONFIG_FILE -d start
  305. ExecReload=/bin/kill -s HUP \$MAINPID
  306. ExecStop=/bin/kill -s TERM \$MAINPID
  307. [Install]
  308. WantedBy=multi-user.target
  309. EOF
  310. systemctl daemon-reload
  311. systemctl enable shadowsocksR && systemctl restart shadowsocksR
  312. sleep 3
  313. res=`netstat -nltp | grep ${PORT} | grep python`
  314. if [ "${res}" = "" ]; then
  315. colorEcho $RED " ssr启动失败,请检查端口是否被占用!"
  316. exit 1
  317. fi
  318. }
  319. setFirewall() {
  320. systemctl status firewalld > /dev/null 2>&1
  321. if [[ $? -eq 0 ]];then
  322. firewall-cmd --permanent --add-service=http
  323. firewall-cmd --permanent --add-port=${PORT}/tcp
  324. firewall-cmd --permanent --add-port=${PORT}/udp
  325. firewall-cmd --reload
  326. else
  327. nl=`iptables -nL | nl | grep FORWARD | awk '{print $1}'`
  328. if [[ "$nl" != "3" ]]; then
  329. iptables -I INPUT -p tcp --dport 80 -j ACCEPT
  330. iptables -I INPUT -p tcp --dport ${PORT} -j ACCEPT
  331. iptables -I INPUT -p udp --dport ${PORT} -j ACCEPT
  332. fi
  333. fi
  334. }
  335. installBBR() {
  336. result=$(lsmod | grep bbr)
  337. if [ "$result" != "" ]; then
  338. colorEcho $GREEN " BBR模块已安装"
  339. INSTALL_BBR=false
  340. return
  341. fi
  342. res=`hostnamectl | grep -i openvz`
  343. if [ "$res" != "" ]; then
  344. colorEcho $YELLOW " openvz机器,跳过安装"
  345. INSTALL_BBR=false
  346. return
  347. fi
  348. echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
  349. echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
  350. sysctl -p
  351. result=$(lsmod | grep bbr)
  352. if [[ "$result" != "" ]]; then
  353. colorEcho $GREEN " BBR模块已启用"
  354. INSTALL_BBR=false
  355. return
  356. fi
  357. colorEcho $BLUE " 安装BBR模块..."
  358. rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
  359. rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm
  360. yum --enablerepo=elrepo-kernel install kernel-ml -y
  361. yum remove kernel-3.* -y
  362. grub2-set-default 0
  363. echo "tcp_bbr" >> /etc/modules-load.d/modules.conf
  364. INSTALL_BBR=true
  365. }
  366. info() {
  367. port=`grep server_port $CONFIG_FILE| cut -d: -f2 | tr -d \",' '`
  368. res=`netstat -nltp | grep ${port} | grep python`
  369. [ -z "$res" ] && status="${RED}已停止${PLAIN}" || status="${GREEN}正在运行${PLAIN}"
  370. password=`grep password $CONFIG_FILE| cut -d: -f2 | tr -d \",' '`
  371. method=`grep method $CONFIG_FILE| cut -d: -f2 | tr -d \",' '`
  372. protocol=`grep protocol $CONFIG_FILE| cut -d: -f2 | tr -d \",' '`
  373. obfs=`grep obfs $CONFIG_FILE| cut -d: -f2 | tr -d \",' '`
  374. p1=`echo -n ${password} | base64 -w 0`
  375. p1=`echo -n ${p1} | tr -d =`
  376. res=`echo -n "${IP}:${port}:${protocol}:${method}:${obfs}:${p1}/?remarks=&protoparam=&obfsparam=" | base64 -w 0`
  377. res=`echo -n ${res} | tr -d =`
  378. link="ssr://${res}"
  379. echo ""
  380. echo ============================================
  381. echo -e " ${BLUE}ssr运行状态:${PLAIN}${status}"
  382. echo -e " ${BLUE}ssr配置文件:${PLAIN}${RED}$CONFIG_FILE${PLAIN}"
  383. echo ""
  384. echo -e " ${RED}ssr配置信息:${PLAIN}"
  385. echo -e " ${BLUE}IP(address):${PLAIN} ${RED}${IP}${PLAIN}"
  386. echo -e " ${BLUE}端口(port):${PLAIN}${RED}${port}${PLAIN}"
  387. echo -e " ${BLUE}密码(password):${PLAIN}${RED}${password}${PLAIN}"
  388. echo -e " ${BLUE}加密方式(method):${PLAIN} ${RED}${method}${PLAIN}"
  389. echo -e " ${BLUE}协议(protocol):${PLAIN} ${RED}${protocol}${PLAIN}"
  390. echo -e " ${BLUE}混淆(obfuscation):${PLAIN} ${RED}${obfs}${PLAIN}"
  391. echo
  392. echo -e " ${BLUE}ssr链接:${PLAIN} $link"
  393. echo $link > ssr.txt
  394. # qrencode -o - -t utf8 $link
  395. }
  396. bbrReboot() {
  397. if [ "${INSTALL_BBR}" == "true" ]; then
  398. echo
  399. echo 为使BBR模块生效,系统将在30秒后重启
  400. echo
  401. echo -e " 您可以按 ctrl + c 取消重启,稍后输入 ${RED}reboot${PLAIN} 重启系统"
  402. sleep 30
  403. reboot
  404. fi
  405. }
  406. install() {
  407. echo -n "系统版本: "
  408. cat /etc/centos-release
  409. checkSystem
  410. # getData
  411. preinstall
  412. # installBBR
  413. installSSR
  414. # setFirewall
  415. info
  416. # bbrReboot
  417. }
  418. uninstall() {
  419. echo ""
  420. read -p " 确定卸载SSR吗?(y/n)" answer
  421. [ -z ${answer} ] && answer="n"
  422. if [ "${answer}" == "y" ] || [ "${answer}" == "Y" ]; then
  423. rm -f $CONFIG_FILE
  424. rm -f /var/log/shadowsocks.log
  425. rm -rf /usr/local/shadowsocks
  426. systemctl disable shadowsocksR && systemctl stop shadowsocksR && rm -rf /usr/lib/systemd/system/shadowsocksR.service
  427. fi
  428. echo -e " ${RED}卸载成功${PLAIN}"
  429. }
  430. slogon
  431. action=$1
  432. [ -z $1 ] && action=install
  433. case "$action" in
  434. install|uninstall|info)
  435. ${action}
  436. ;;
  437. *)
  438. echo " 参数错误"
  439. echo " 用法: `basename $0` [install|uninstall]"
  440. ;;
  441. esac

新建文件:/etc/anbsible/install-ssr.yaml , 注意该文件拷贝时格式不能错误。

  1. - hosts: ssr
  2. remote_user: root
  3. tasks:
  4. - name: 更新软件源
  5. shell: yum update -y
  6. - name: 安装基础包
  7. shell: yum install libsodium.x86_64 wget -y
  8. - name: 删除之前ssr安装脚本
  9. shell: rm -rf /tmp/*install-ssr*
  10. - name: 拷贝安装脚本到其他机器
  11. copy:
  12. src: /root/install-ssr-server.sh
  13. dest: /tmp/install-ssr.sh
  14. - name: 修改脚本权限777
  15. shell: chmod 777 /tmp/install-ssr.sh
  16. - name: 开始安装ssr服务
  17. shell: sh /tmp/install-ssr.sh

二、开始使用 ansible

1.给所有机器安装 ssr 服务

  1. # 该命令在主节点上执行
  2. ansible playbook /etc/ansible/install-ssr.yaml
  3. # 等待该命令运行完毕即可,运行时长和被控制机器数量有关。

2.获取所有机器上所有的ssr地址信息

  1. # 其中 ssr 是上面配置文件中的标签名字,可以根据实际情况进行修改
  2. ansible ssr -a 'cat /root/ssr.txt' | grep ssr > ssr-info.txt
  3. # 下面这条命令导出ssr地址信息会包含对应的vps公网ip
  4. ansible ssr -m shell -a 'AA=`cat /root/ssr.txt` && BB=`curl -s ip.sb` && echo -e "$AA\t$BB"' | grep ssr > ssr-info.txt
  5. # 执行该命令之后,会在当前路径下生成已给 ssr-info.txt 文件,该文件包含所有机器上启用的ssr地址。

建议:主节点配置好一点可以提高部署速度

异常处理:

出现以下异常提示:
fatal: [13.229.56.59]: FAILED! => {“msg”: “Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host’s fingerprint to your known_hosts file to manage this host.”}

  1. # 重新设置一下环境变量
  2. export ANSIBLE_HOST_KEY_CHECKING=False