0%

家庭组网

组网方案

概述

实现外网千兆内网2.5G网络方案

组网方案

设备组成

  1. 猫棒
  2. N5105 4口2.5G软路由一台做主路由(PEV虚拟机跑pfsense, openwrt, homeassistant)
  3. TP-LINK 8口2.5G交换机
  4. 2台TP-Link mesh路由器
  5. 群晖NAS DS920+ (家庭影音中心,文件存储)

Promox VE

虚拟机安装pfsense 和 openwrt

网络规划

设备 IP Address
promox ve 192.168.10.250
pfsense 主路由 192.168.10.1
openwrt 旁路由 192.168.10.2
ubuntu server 192.168.10.251
homeassistant 192.168.10.252
desk-top 192.168.10.253
群晖NAS 192.168.10.254

pfSense openvpn server setup

reference: https://www.sparklabs.com/support/kb/article/setting-up-an-openvpn-server-with-pfsense-and-viscosity/

setup with ipv6

openvpn protocol -> UDP on IPV6 only
Firewall -> Rules -> WAN / OpenVPN -> Address Family -> IPV4 + IPV6

ipv6 setup

reference: https://blog.51cto.com/fxn2025/2454377

  • Interfaces -> WAN

IPv6 Configuration Type : DHCP6

Use IPv4 connectivity as parent interface: Yes

DHCPv6 Prefix Delegation size: 60

Send IPv6 prefix hint: Yes

Do not allow PD/Address release : Yes

  • Interfaces -> LAN

IPv6 Configuration Type: Track Interface

IPv6 Interface: WAN

  • Services -> DHCPV6 Server & RA -> Router Advertisements

Router mode: Assisted

aliyun DDNS

方案

  • 方案一

    通过修改源码新增DDNS

  • 方案二

    通过局域网内服务器安装selenium模拟网页登录,获取pfSense的ip来更新

  • 方案三

    通过局域网内服务器安装pfsense-fauxapi 获取pfSense的ip来更新

方案一貌似还是通过外部地址http://checkip.dyndns.org来获取ip,可能会不准或地址失效,方案二和三原理相同,为了布置在服务器上比较方便,这边选择方案三来部署。

部署

  1. 在Proxmox VE上安装ubuntu server

  2. 安装pip及venv

    1
    2
    $ sudo apt install python3-pip
    $ sudo apt install python3.10-venv
  3. 激活python虚拟环境(可选)

    1
    2
    $ python -m venv env
    $ source env/bin/active
  4. 安装依赖

    https://github.com/ndejong/pfsense_fauxapi#user-content-config_get

    1
    2
    3
    $ pip install pfsense-fauxapi
    $ pip install alibabacloud_tea_openapi
    $ pip install alibabacloud_alidns20150109==2.0.2
  5. 运行代码

    1
    $ python aliyun_ddns.py
  6. 成功后加入定时任务

    1
    2
    3
    $ crontab -e
    # 每五分钟执行一次
    */5 * * * * python

参考代码

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
60
61
62
63
64
65
66
67
68
69
from PfsenseFauxapi.PfsenseFauxapi import PfsenseFauxapi

from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_alidns20150109.client import Client as Client
from alibabacloud_alidns20150109 import models as models
from alibabacloud_tea_util.client import Client as UtilClient

import logging

logging.basicConfig(format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S', filename='ddns.log', level=logging.INFO)

current_ip_addr = ''

# pfSense config
fauxapi_host = '192.168.10.1'
apikey = '******************'
apisecret = '******************'

# config aliyun dynamic dns
access_key_id = '******************'
access_key_secret = '******************'
endpoint = 'alidns.cn-hangzhou.aliyuncs.com'
domain_name = 'example.com'
rr='www'
type='AAAA'

def get_interfacestatus():
FauxapiLib = PfsenseFauxapi(fauxapi_host, apikey, apisecret)

# get current ipv6 address
interfacestatus = FauxapiLib.system_stats()['data']['stats']['interfacestatus']
ipv6addr = interfacestatus.split('^')[3]
is_linked = interfacestatus.split('^')[1]
return is_linked, ipv6addr

def update_record():
# config
config = open_api_models.Config(
# 您的AccessKey ID,
access_key_id=access_key_id,
# # 您的AccessKey Secret,
access_key_secret=access_key_secret)
# 访问的域名
config.endpoint = endpoint
client = Client(config)

describe_domain_records_request = models.DescribeDomainRecordsRequest(domain_name=domain_name, rrkey_word=rr,type=type)
resp = client.describe_domain_records(describe_domain_records_request)
record = resp.body.domain_records.record[0]
# 记录ID
record_id = record.record_id
# 记录值
records_value = record.value
logging.info('Previous record value is: %s.' % records_value)
if not UtilClient.equal_string(current_ip_addr, records_value):
update_domain_records_request = models.UpdateDomainRecordRequest(record_id=record_id, rr=rr, type=type, value=current_ip_addr)
client.update_domain_record(update_domain_records_request)
logging.info('Updated record value : %s.' % current_ip_addr)

if __name__ == '__main__':
if get_interfacestatus()[0] == 'up':
current_ip_addr = get_interfacestatus()[1]
if current_ip_addr:
update_record()
else:
logging.warning('Can not get the ipv6 address!')
else:
logging.warning('Can not get the ipv6 address. Please check the wan interface!')