格物、致知、诚意、正心

0%

安装

安装这块我就不细讲了,不论是用 Docker 还是 Helm ,官方的文档永远是最好的参考。我这边是用 HelmKubernetes 上安装的。安装其实很简单,

环境变量

官方的 Docker 镜像中,环境变量有一些是只在初始化过程中有用的。比如:LDAP_DOMAINLDAP_ADMIN_PASSWORD 后期一般在 OpenLDAP 内部自己改即可。

Helm 配置

创建自定义的配置文件

1
vi values.yaml

添加配置,注意修改域名和密码为自己的。我这边由于是在集群中使用,因此没有开 TLS。开启只读用户并且配置,用来让其他平台的服务读取 LDAP 配置,使用其登陆。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
nameOverride: ldap
fullnameOverride: ldap

# Use the env variables from https://github.com/osixia/docker-openldap#beginner-guide
env:
LDAP_ORGANISATION: "Retirwer Technology Co., Ltd"
LDAP_DOMAIN: "retirwer.com"
LDAP_BACKEND: "hdb"
LDAP_TLS: "false"
LDAP_TLS_ENFORCE: "false"
LDAP_REMOVE_CONFIG_AFTER_SETUP: "true"
LDAP_READONLY_USER: "true"
LDAP_READONLY_USER_USERNAME: "readonly"
LDAP_READONLY_USER_PASSWORD: "<password>"

# Default Passwords to use, stored as a secret. If unset, passwords are auto-generated.
# You can override these at install time with
# helm install openldap --set openldap.adminPassword=<passwd>,openldap.configPassword=<passwd>
adminPassword: <passwd>
configPassword: <passwd>

部署

1
helm install ldap stable/openldap -f values.yaml

一般情况下,访问地址是

1
ldap.<namespace>.svc.cluster.local

配置

OpenLDAP 虽然应用非常广泛,但网上资料却少的可怜。如果你有 Kindle Unlimited,上面有一本郭大勇写的《Linux/UNIX OpenLDAP实战指南》可以免费做参考。如果没有则不建议去买,普通用户只能用到一点点里面的知识,如果你是真正的运维可以考虑买来看看。

客户端

客户端我推荐 Apache Directory Studio,毕竟 LDAP 的配置是在是太难了!普通用户没必要去学习配置脚本甚至命令,开源跨平台图形化界面的配置工具足够好用。

安装 Apache Directory Studio

1
brew cask install apache-directory-studio

管理内容

管理用户账户、群组和设备,用此方式登陆。

使用以下 DNadminPassword 登陆,域名需要配置成自己的域名,如果有三层,就配置三层 dc

1
cn=admin,dc=retirwer,dc=com

管理配置

管理基础配置、权限控制等,用此方式登陆。

使用以下 DNconfigPassword 登陆

1
cn=admin,dc=config

接入配置

第三方平台接入登陆,比如 GitlabHarborJenkins等等。需要读取用户和群组信息,使用只读账户。

使用以下 DNLDAP_READONLY_USER_PASSWORD 登陆

1
cn=<LDAP_READONLY_USER_USERNAME>,dc=retirwer,dc=com

权限配置

参考官方文档: https://www.openldap.org/doc/admin24/access-control.html

参考

Harbor

Harbor 是一个企业级 Registry 服务器,可以用来存放 Docker 镜像,还可以存放 Helm Chats。

Proxy

Nginx 代理,用来转发请求。用 Ingress 之后此模块不会开启。

Registry

负责存储 Docker 镜像,内核是 Docker 官方的 Registry。

由于 Registry 没有权限认证,所有 Harbor 对每次请求都会进行鉴权,通过之后再由 Registry 处理。

Core

Harbor的核心功能,主要包含以下功能:

  • 认证与授权
  • 配置管理
  • 元数据管理
  • 内容管理与分发

其他组件

Chart Museum:Helm Chart 仓库。

Job Services:处理异步计算请求。

Log collector:日志收集。

Notary:信任中心,详情:https://github.com/theupdateframework/notary

Web Portal:图形化的用户页面,用户通过这个管理 Registry。

安装

添加仓库

1
2
helm repo add harbor https://helm.goharbor.io
helm repo add bitnami https://charts.bitnami.com/bitnami

更新

1
helm repo update

配置

获取配置条目

1
helm inspect values harbor/harbor

可以保存为文件,后续参考方便

1
helm inspect values harbor/harbor > origin.yaml

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 密码
harborAdminPassword: "Harbor12345"
# 用于加密的一个 secret key,必须是一个16位的字符串
secretKey: "not-a-secure-key"

# 对外暴露配置
expose:
type: ingress
tls:
enabled: true
secretName: harbor-tls
notarySecretName: harbor-tls
ingress:
hosts:
core: registry.harbor.com
notary: notary.harbor.com
annotations:
kubernetes.io/ingress.class: "nginx"

ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"

ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-body-size: "0"

# 外部地址
externalURL: https://registry.harbor.com

# 持久存储
persistence:
enabled: true
# Setting it to "keep" to avoid removing PVCs during a helm delete
# operation. Leaving it empty will delete PVCs after the chart deleted
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
existingClaim: "oss-pvc"
subPath: "register"
accessMode: ReadWriteMany
chartmuseum:
existingClaim: "oss-pvc"
subPath: "chartmuseum"
accessMode: ReadWriteMany
jobservice:
existingClaim: "host-pvc"
subPath: "jobservice"
accessMode: ReadWriteMany
database:
existingClaim: "host-pvc"
subPath: "database"
accessMode: ReadWriteMany
redis:
existingClaim: "host-pvc"
subPath: "redis"
accessMode: ReadWriteMany
trivy:
existingClaim: "host-pvc"
subPath: "trivy"
accessMode: ReadWriteMany

主要配置密码和密钥,以及域名与证书。

存储我这边分了两部分:

  • oss-pvc 是阿里云的 OSS,主要保存 Docker 镜像和 Helm Chars。
  • host-pvc 则是服务器本机的目录,需要高性能的数据库都用这个,后续会增加备份。没有必要区分的数据也放在本机。

安装

配置正确之后只需要使用 Helm 安装即可。

1
helm install harbor harbor/harbor -f values.yaml . --namespace NAMESPACE

安装成功之后打开配置的 externalURL,即可访问。用户名 admin,密码是配置的 harborAdminPassword

测试

使用命令行登陆

1
docker login https://register.harbor.com

下载一个官方的镜像

1
docker pull alpine:3.9

新建标签

1
docker tag alpine:3.9 register.harbor.com/library/alpine:3.9

上传

1
docker push register.harbor.com/library/alpine:3.9

Charts 管理

添加仓库

1
helm repo add --username=<username> --password=<password> <repo-name> https://<harbor-domain>/chartrepo/<project>

安装 PUSH 插件

默认的 Helm 没有推送功能,需要安装插件才可以。

1
helm plugin install https://github.com/chartmuseum/helm-push

上传 Charts

1
helm push <charts-dir> <repo>

参考

插件选择

Kubernetes 与外部存储对接时要使用插件,自定义插件有很多协议。阿里云支持的插件为 FlexvolumeCSI,需要选择用哪一个插件搭建系统。由于 CSI 比较新,而且社区推荐使用,我这边就选择了 CSI。

Flexvolume

Flexvolume插件是Kubernetes社区较早实现的存储卷扩展机制。ACK从上线起,即支持Flexvolume类型数据卷服务。Flexvolume插件包括以下三部分。

  • Flexvolume:负责数据卷的挂载、卸载功能。ACK默认提供云盘、NAS、OSS三种存储卷的挂载能力。
  • Disk-Controller:负责云盘卷的自动创建能力。
  • Nas-Controller:负责NAS卷的自动创建能力。

CSI

CSI插件是当前Kubernetes社区推荐的插件实现方案。ACK集群提供的CSI存储插件兼容社区的CSI特性。CSI插件包括以下两部分:

  • CSI-Plugin:实现数据卷的挂载、卸载功能。ACK默认提供云盘、NAS、OSS三种存储卷的挂载能力。
  • CSI-Provisioner:实现数据卷的自动创建能力,目前支持云盘、NAS两种存储卷创建能力。

安装插件

命名空间

1
kubectl create namespace cloud-retirwer-k8s-plugin

RBAC

下载 RBAC 配置

1
wget https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/master/deploy/rbac.yaml

修改 namespace ,后续的所有配置也都要修改命名空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
# replace with the same namespace name with plugin
namespace: cloud-retirwer-k8s-plugin

---
# 省略权限配置
---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: alicloud-csi-plugin
subjects:
- kind: ServiceAccount
name: admin
namespace: cloud-retirwer-k8s-plugin
roleRef:
kind: ClusterRole
name: alicloud-csi-plugin
apiGroup: rbac.authorization.k8s.io

加载配置

1
kubectl apply -f rbac.yaml

OSS-Plugin

下载配置

1
wget https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/master/deploy/oss/oss-plugin.yaml

修改 namespace

1
2
3
4
5
kind: DaemonSet
apiVersion: apps/v1beta2
metadata:
name: csi-ossplugin
namespace: cloud-retirwer-k8s-plugin

加载配置

1
kubectl apply -f oss-plugin.yaml

常见问题如下,k8s 高版本对于 beta 版 API 有所更改。

1
error: unable to recognize "oss-plugin.yaml": no matches for kind "DaemonSet" in version "apps/v1beta2"

如果碰见以上问题 ,则将版本修改为 V1

1
2
kind: DaemonSet
apiVersion: apps/v1

测试

需要提前创建好 OSS Bucket,配置好权限,获得访问密钥。

下载测试配置

1
2
3
wget https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/master/examples/oss/deploy.yaml
wget https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/master/examples/oss/pv.yaml
wget https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/master/examples/oss/pvc.yaml

修改配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: PersistentVolume
metadata:
name: oss-csi-pv
labels:
alicloud-pvname: oss-csi-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
# set volumeHandle same value pv name
volumeHandle: oss-csi-pv
volumeAttributes:
bucket: "<*>"
url: "oss-cn-hangzhou.aliyuncs.com"
otherOpts: "-o max_stat_cache_size=0 -o allow_other"
akId: "<*>"
akSecret: "<*>"
path: "/test"

加载配置

1
2
3
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
kubectl apply -f deploy.yaml

检查运行状态,如果三个都正常就没问题了

1
2
3
kubectl get pv | grep oss
kubectl get pvc | grep oss
kubectl get pod | grep oss

使用

PV

使用此 CSI 主要是需要在定义 PV 的配置中做特殊配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-name
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
# 回收模式 一定要选保留
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
# set volumeHandle same value pv name
volumeHandle: oss-csi-pv
volumeAttributes:
bucket: "<*>"
url: "oss-cn-hangzhou.aliyuncs.com"
otherOpts: "-o max_stat_cache_size=0 -o allow_other"
akId: "<*>"
akSecret: "<*>"
path: "/test"

存储大小

1
2
3
# 定义存储大小,Gi 代表以 1024 的算法进行计算大小
capacity:
storage: 5Gi

访问模式

1
2
3
# 访问模式 OSS 支持 ReadWriteMany
accessModes:
- ReadWriteOnce

回收模式

1
persistentVolumeReclaimPolicy: Retain

回收模式一般要选保留,不排除特殊情况

CSI

1
2
3
4
5
6
7
8
9
10
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: oss-csi-pv
volumeAttributes:
bucket: "<*>"
url: "oss-cn-hangzhou.aliyuncs.com"
otherOpts: "-o max_stat_cache_size=0 -o allow_other"
akId: "<*>"
akSecret: "<*>"
path: "/test"

driver 是所要挂载的驱动,需要和之前安装的相同,如果你用其他厂家或者是不同的产品,根据情况调整。volumeHandle 唯一标识从 CSI 卷插件的 CreateVolume 调用返回的卷名。随后在卷驱动程序的所有后续调用中使用卷句柄来引用该卷,一般和 PV 名称相同。volumeAttributes 则是外部服务提供商自己定义的值,OSS 目前是这些配置,其他厂家有不同的配置。

PVC

不需要做特殊配置。选择器需要匹配自己想要使用的 PV。

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: oss-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
selector:
matchLabels:
alicloud-pvname: oss-csi-pv

参考

应用介绍

目标是将公司网站发布到集群中。前期准备:域名备案,编写代码与打包镜像。由于目前还是简易的纯前端展示页面,以及基础设施还不太完善,我就直接将镜像放到 DockerHub 上了。

源码

https://github.com/Retirwer/www.retirwer.com

镜像

https://hub.docker.com/repository/docker/retirwer/www.retirwer.com

集群环境

CertManager

用来自动申请 HTTPS 证书。

Helm

用来进行 Kubernetes 应用的管理。

应用配置

创建 Helm Chars

1
helm create www.retirwer.com

由于基本模板对于简单的展示站够用,目前只需要修改 Chart.yamlvalues.yaml 文件即可。

Chart.yaml

1
2
3
4
5
6
apiVersion: v2
name: www.retirwer.com
description: Retirwer Technology Co., Ltd Official Web Site.
type: application
version: 0.1.0
appVersion: 0.0.1

values.yaml

修改镜像,版本则和 appVersion 相同,后续更改版本只需要修改 Chart.yaml 中的 appVersion

1
2
3
image:
repository: retirwer/www.retirwer.com
pullPolicy: IfNotPresen

配置 Ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ingress:
enabled: true
annotations:
# 使用 Nginx-Ingress 的配置
kubernetes.io/ingress.class: nginx
# 根据自己的 cert-manager 的配置修改
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: www.retirwer.com
# 只配置根目录
paths: [/]
tls:
- secretName: www.retirwer.com-tls
hosts:
- www.retirwer.com

其他

  • 对于其他用不到的配置模版可以删掉,也可以不启用。

发布

一般必须指定命名空间,如果不指定则使用当前命名空间。

确认发布配置

1
helm install <release-name> . --debug --dry-run

首次发布

1
helm install <release-name> . --namespace <namespace>

更新发布

1
helm upgrade <release-name> . --namespace <namespace>

卸载发布

1
helm uninstall <release-name> --namespace <namespace>

经验总结

我的集群是自建的独立 ETCD 集群,然后其他组件全部用 kubeadm 来进行安装的,升级起来比较方便。

一般来说,只有第一台 Master 需要的操作比较多,后续的 Master 和 Node 操作基本相同。如果经常升级的话,倒是可以写一个脚本去做,我因为第一次做 K8S 的升级。不太熟,所以全程手动升级的。

过程中使用 Tmux 进行远程链接安全性的保证。如果因为某些操作中途中断导致升级失败,那麻烦就大了。

升级要求

  • 必须在 1.17 以上版本
  • 必须使用外部 ETCD
  • 切记备份数据

确定目标版本

1
2
apt update
apt-cache madison kubeadm

得到最新版本 1.18.2-00

升级主节点集群

开始升级第一个主节点

升级 kubeadm

1
2
3
apt-mark unhold kubeadm && \
apt-get update && apt-get install -y kubeadm=1.18.2-00 && \
apt-mark hold kubeadm

确认版本

1
kubeadm version

清空节点上的容器

1
kubectl drain <cp-node-name> --ignore-daemonsets

在需要升级的节点上运行

1
kubeadm upgrade plan

选择要升级到的版本,然后运行相应的命令

1
kubeadm upgrade apply v1.18.2

升级完成之后需要升级 kubelet 和 kubectl :

1
2
3
apt-mark unhold kubelet kubectl && \
apt-get update && apt-get install -y kubelet=1.18.2-00 kubectl=1.18.2-00 && \
apt-mark hold kubelet kubectl

重启 kubelet

1
systemctl restart kubelet

取消节点限制策略

1
kubectl uncordon <cp-node-name>

升级其他主节点

先升级 kubeadm

1
2
3
apt-mark unhold kubeadm && \
apt-get update && apt-get install -y kubeadm=1.18.2-00 && \
apt-mark hold kubeadm

然后清空节点:

1
kubectl drain <cp-node-name> --ignore-daemonsets

执行升级命令

1
kubeadm upgrade node

升级完成之后需要升级 kubelet 和 kubectl :

1
2
3
apt-mark unhold kubelet kubectl && \
apt-get update && apt-get install -y kubelet=1.18.2-00 kubectl=1.18.2-00 && \
apt-mark hold kubelet kubectl

重启 kubelet

1
systemctl restart kubelet

取消节点限制策略

1
kubectl uncordon <cp-node-name>

升级工作节点

升级工作节点的步骤与升级其他主节点步骤相同。

其他

网络插件按需升级,我这边暂时没有升级的需求,就没有升级了。

参考

INIT

Change Password

1
password

WAN

1
2
3
4
5
6
7
8
9
10
11
# Config Static IP
uci set network.wan.proto=static
uci set network.wan.ipaddr=10.10.10.5
uci set network.wan.netmask=255.255.255.0
uci set network.wan.gateway=10.10.10.1

# Review Config
uci export network

# Commit UCI Config, need restart network to working.
uci commit

LAN

Use edit config files way.

1
2
3
4
5
6
7
8
9
10
vi /etc/config/network

config interface 'lan'
option type 'bridge'
option ifname 'eth0'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option dns '10.10.10.1'
option ip6assign '60'

WLAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Enable Wireless Device
uci set wireless.@wifi-device[0].disabled=0

# Config Wireless
uci set wireless.@wifi-iface[0].mode=ap
uci set wireless.@wifi-iface[0].ssid=TSFuShui
uci set wireless.@wifi-iface[0].encryption=psk2
uci set wireless.@wifi-iface[0].key=88888888
uci set wireless.@wifi-iface[0].network=lan

# Review Config
uci export wireless

# Commit UCI Config, need restart network to working.
uci commit

TEST

1
2
3
4
5
# Restart network to apply config
/etc/init.d/network restart

# If ping is ok, Good Net.
ping 1.1.1.1

PACKAGE

1
2
3
4
5
6
7
8
9
10
11
# update package list
opkg update

# show upgrable pkg
opkg list-upgradable

# upgrade one pkg
opkg upgrade <pkg>

# upgrade all pkg
opkg list-upgradable | cut -f 1 -d ' ' | xargs opkg upgrade

基本操作

ROS 命令行一个命令其实逻辑上会进入到对应的目录,只有最后一个执行文件才会真正执行,所以可以用这种操作简化命令输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 输入 system 其实进入了 system 目录, 之后进入 routerboard 目录,
[admin@MikroTik] > system
[admin@MikroTik] /system> routerboard
[admin@MikroTik] /system routerboard>

# 再输入最后的可执行命令,就执行了 print 命令
[admin@MikroTik] /system routerboard> print
routerboard: yes
model: RB4011iGS+
serial-number: B8FF0B97D030
firmware-type: al2
factory-firmware: 6.44.5
current-firmware: 6.44.6
upgrade-firmware: 6.44.6

# 如果想回到根目录,使用 /
[admin@MikroTik] /system routerboard> /
[admin@MikroTik] >

# 在命令行中随时输入 ? 会弹出命令和帮助
[admin@MikroTik] /ip address>
IP addresses are given to router to access it remotely and to specify it as a gateway for other hosts/routers.

.. -- go up to ip
add -- Create a new item
comment -- Set comment for items
disable -- Disable items
edit --
enable -- Enable items
export -- Print or save an export script that can be used to restore configuration
find -- Find items by value
get -- Gets value of item's property
print -- Print values of item properties
remove -- Remove item
set -- Change item properties

新机联网

修改默认配置

1
2
3
4
5
# 修改默认的空密码为自定义的密码
/password

# 关闭一些不用的服务 ( 我这边只保留了 ssh 和 winbox )
/ip service disable telnet,ftp,www,api,api-ssl

配置公网

由于目前都是光猫直接拨号,一般情况只需要配置IP即可。

1
2
3
4
5
6
7
8
# 修改与光猫连接端口名称 
/interface ethernet set ether1 name=WAN-CT-HOME

# 配置光猫内网IP 针对与光猫链接的端口
/ip address add address=192.168.1.2/24 interface=WAN-CT-HOME

# 可以尝试 ping 光猫测试是否成功
/ping 192.168.1.1

内网配置

网络配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 新建网桥
/interface bridge add name=bridge

# 将接口加入网桥
/interface bridge port add bridge=bridge interface=ether5 hw=yes
/interface bridge prot add bridge=bridge interface=ether6 hw=yes
...

# 在网桥上绑定 IP
/ip address add address=10.10.10.1/24 interface=bridge

# 添加默认网关
/ip route add gateway=192.168.1.1

# 出口 SNAT 转换
/ip firewall nat add chain=srcnat action=masquerade

DNS 和 DHCP

1
2
3
4
5
6
7
8
9
10
11
# 配置 DNS 并且允许其他设备访问
/ip dns set servers=1.1.1.1,114.114.114.114 allow-remote-requests=yes

# 新建 IP 池
/ip pool add ranges=10.10.10.100-10.10.10.200 name=NET-POOL

# 建立 DHCP 服务器
/ip dhcp-server add name=NET-DHCP interface=bridge address-pool=NET-POOL

# 配置 DHCP 网络
/ip dhcp-server network add address=10.10.10.0/24 dns-server=10.10.10.1 gateway=10.10.10.1

VLAN

内网 VLAN 配置

网桥

1
2
3
4
5
6
7
8
9
10
11
12
13
# 新建支持 VLAN 的网桥
/interface bridge add name=bridge vlan-filtering=no

# 将端口加入网桥 并配置 VLAN
/interface bridge port add bridge=bridge interface=ether5 pvid=10 hw=yes
/interface bridge prot add bridge=bridge interface=ether6 pvid=10 hw=yes
...

# 在网桥上新建路由器使用的 VLAN
/interface vlan add interface=bridge name=VLAN-NET vlan-id=10

# 在 VLAN 上绑定 IP
/ip address add address=10.10.10.1/24 interface=VLAN-NET

VLAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 开启入口流量过滤 提高安全性
/interface bridge port
set [f] ingress-filtering=yes

# 设置网桥端口过滤 VLAN 标签模式
/interface bridge port
# 允许所有类型帧通过
set [find where interface=<接口>] frame-types=admit-all
# 只允许打了合适 VLAN 标签的帧通过
set [find where interface=<接口>] frame-types=admit-only-vlan-tagged
# 允许未打标签和优先标签通过
set [find where interface=<接口>] frame-types=admit-only-untagged-and-priority-tagged

# 配置网桥 VLAN
# 针对 VLAN 10,sfp1 打标签,ether1,ether2 去掉标签
add bridge=bridge vlan-ids=10 tagged=sfp1 untagged=ether1,ether2
# 如果网桥自身也要转发,需要配置网桥自身
add bridge=bridge tagged=bridge,ether1 vlan-ids=1

Firewall

NAT

查看现有的NAT

1
2
3
4
[admin@MikroTik] /ip firewall nat> print
Flags: X - disabled, I - invalid, D - dynamic
0 ;;; defconf: masquerade
chain=srcnat action=masquerade out-interface-list=WAN ipsec-policy=out,none

目前是默认配置,对于所有 WAN 接口列表中的接口,都使用改变源IP的方式做NAT。

配置端口转发

1
2
# 将外网8000端口映射到内网服务器上的80端口
/ip firewall nat add chain=dstnat protocol=tcp dst-port=8000 in-interface=ether5 action=dst-nat to-addresses=10.10.10.80 to-ports=80

Filter

1
2
3
4
# 允许已经建立的链接通过
/ip firewall filter add chain=input connection-state=established,related in-interface=WAN-CT-DIRECT action=drop
# 过滤掉所有的外部链接进入
/ip firewall filter add chain=input in-interface=WAN-CT-DIRECT action=drop

WAN 负载均衡

标记公网网卡进入的链接

1
2
3
/ip firewall mangle
add action=mark-connection chain=prerouting in-interface=WAN-CT-DIRECT connection-mark=no-mark new-connection-mark=WAN_DIRECT
add action=mark-connection chain=prerouting in-interface=WAN-CT-HOME connection-mark=no-mark new-connection-mark=WAN_HOME

创建 PCC 规则

https://wiki.mikrotik.com/wiki/Manual:PCC

1
2
3
4
# 未标记的内网流量根据算法选择路由出去
/ip firewall mangle
add chain=prerouting in-interface=LAN connection-mark=no-mark dst-address-type=!local action=mark-connection new-connection-mark=WAN_DIRECT per-connection-classifier=both-address:2/0
add chain=prerouting in-interface=LAN connection-mark=no-mark dst-address-type=!local action=mark-connection new-connection-mark=WAN_HOME per-connection-classifier=both-address:2/1

建立路由标记

1
2
3
4
5
6
7
/ip firewall mangle 
add chain=prerouting connection-mark=WAN_DIRECT in-interface=LAN action=mark-routing \
new-routing-mark=TO_WAN_DIRECT
add chain=prerouting connection-mark=WAN_HOME in-interface=LAN action=mark-routing \
new-routing-mark=TO_WAN_HOME
add chain=output connection-mark=WAN_DIRECT action=mark-routing new-routing-mark=TO_WAN_DIRECT
add chain=output connection-mark=WAN_HOME action=mark-routing new-routing-mark=TO_WAN_HOME

创建路由

策略路由 distance 默认为 0,之后创建备用的 distance 为 1 的路由备用

1
2
3
4
5
/ip route
add dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-mark=TO_WAN_DIRECT check-gateway=ping
add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-mark=TO_WAN_HOME check-gateway=ping
add dst-address=0.0.0.0/0 gateway=192.168.1.1 distance=1 check-gateway=ping
add dst-address=0.0.0.0/0 gateway=192.168.2.1 distance=2 check-gateway=ping

SNAT

1
2
3
/ ip firewall nat 
add chain=srcnat out-interface=WAN-CT-DIRECT action=masquerade
add chain=srcnat out-interface=WAN-CT-HOME action=masquerade

策略路由

防止策略路由导致的路由环路,处理 WAN 的局部网络

1
2
3
/ ip firewall mangle
add chain=prerouting dst-address=192.168.1.0/24 action=accept in-interface=LAN
add chain=prerouting dst-address=192.168.2.0/24 action=accept in-interface=LAN

安装 JAVA

直接安装最新版本 ( oracle jdk ),其他版本的可从官网下载安装

1
brew cask install java

安装选定版本 ( openjdk )

1
2
3
4
5
brew tap homebrew/cask-versions
brew tap adoptopenjdk/openjdk
brew update
brew cask install adoptopenjdk/openjdk/adoptopenjdk8
# 也可以安装 9/10/11/12/13 等

安装编译工具

安装 Maven

1
brew install maven

安装 Gradle

1
brew install gradle

安装

添加 PPA 仓库

1
2
3
4
5
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update

安装 Certbot

1
sudo apt-get install certbot

签发证书

使用以下命令签发证书

1
sudo certbot certonly --manual --preferred-challenges dns -d gaobo.name

certonly --manual 代表手动签发证书,不进行其他配置工作。

--preferred-challenges dns 代表验证方式使用 DNS 进行域名所有权的验证,也可以选择 http 方式进行验证。

-d gaobo.name 则是域名配置,后面可以多次使用 -d DOMAIN 来配置多个域名。

修改 DNS 解析

在执行上面的命令之后,会有几步相关的操作让你确认。之后会给你一段口令让你设置到 DNS 解析上:

1
2
3
4
5
6
7
8
9
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.gaobo.name with the following value:

aO0HEtcVvHPPGY2a8JHEzjIXcDj8QD0kWb48Xmbh3g8

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

按照提示设置好之后,按回车键即可。

成功签发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/gaobo.name/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/gaobo.name/privkey.pem
Your cert will expire on 2020-02-20. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

出现上面的提示之后就代表成功签发了,接下来只需要在 Web 服务器中进行配置即可。

服务器配置

NGINX

如下所示,配置 ssl_certificatessl_certificate_key 即可。

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 443 ssl;
server_name gaobo.name;

ssl_certificate /etc/letsencrypt/live/gaobo.name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gaobo.name/privkey.pem;

location / {
proxy_pass http://127.0.0.1:8002;
include proxy_params;
}
}

参考

https://certbot.eff.org/docs/using.html#certbot-commands

修改配置文件

编辑 /etc/ssh/sshd_config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 修改 SSH 端口为非常用端口
Port 22222
# 限制登陆过程的时间
LoginGraceTime 5
# 限制登陆过程重试次数
MaxAuthTries 1

# 禁止 Root 用户登陆
PermitRootLogin no
# 禁止空密码
PermitEmptyPasswords no
# 禁止密码登陆
PasswordAuthentication no

# 只允许特定用户登陆
AllowUsers etbyapt

重启服务 systemctl restart ssh

隐藏端口

虽然我们能够更改端口号,和一些配置。但是,仍然有被扫描器扫描到的风险。如何能够让某个端口只在特定的情况下为我们自己开启,然后进行连接呢?我们可以使用 knockd 这个工具来完成这个工作。

knockd 可以检测某些特定端口的特定访问,然后根据配置的规则触发一些事件。事件触发之后就可以通过命令开启某些特定的端口,然后我们就可以进行连接了。

安装配置 knockd

1
sudo apt install knockd

编辑 /etc/knockd.conf

1
2
3
4
5
6
7
8
9
10
11
[options]
LogFile = /var/log/knockd.log
Interface = enp5s0 # 这里使用自己的网卡配置

[opencloseSSH]
sequence = 7000,8000,9000
seq_timeout = 5
tcpflags = syn
start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 30
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

以上配置详解

1
2
3
4
5
6
7
sequence 配置端口号序列 可以使用 22:udp 代表udp的端口号
seq_timeout 连续访问上方序列的时间限制
tcpflags 包的 TCP 标志
start_command 完成序列之后执行的命令
cmd_timeout 结束命令的时间
end_command 结束之后执行的命令
由于防火墙对已经链接成功的包不进行过滤,所以链接之后再关闭包仍然能够通过

启动 knockd

1
2
systemctl enable knockd.service
systemctl start knockd.service

测试 knockd

测试需要安装 knock

1
2
apt install knockd # 客户端和服务器在一个包里面
brew install knock

测试上面配置文件中的端口序列

1
2
3
4
5
$ knock  -v {IP} 7000 8000 9000

hitting tcp 10.10.10.100:7000
hitting tcp 10.10.10.100:8000
hitting tcp 10.10.10.100:9000

查看日志文件 /var/log/knockd.log

1
2
3
4
5
[2019-11-21 20:32] 10.10.10.133: opencloseSSH: OPEN SESAME
[2019-11-21 20:32] opencloseSSH: running command: /sbin/iptables -A INPUT -s 10.10.10.133 -p tcp --dport 22 -j ACCEPT

[2019-11-21 20:32] 10.10.10.133: opencloseSSH: command timeout
[2019-11-21 20:32] opencloseSSH: running command: /sbin/iptables -D INPUT -s 10.10.10.133 -p tcp --dport 22 -j ACCEPT

以上说明配置成功了,之后每次 SSH 之前需要先使用 knock 命令敲门之后再进行连接。

注意

  • knockd 所配置的敲门序列需要搭配 iptables 的包过滤才能真正发挥效果。

  • knockd 的敲门模式不只是可以用来打开端口,也可以执行其他任何操作。

参考

https://www.ibm.com/developerworks/cn/aix/library/au-sshlocks/index.html

http://linux.vbird.org/linux_security/knockd.php