这是我之前的问题的延续,即从 Freeradius DHCP 服务器实现结合 Strongswan VPN 服务器发送静态路由。
在使用 tcpdump 和 Wireshark 调试 Freeradius 时,我发现我可以通过向dhcp 服务器配置文件的我的和部分添加DHCP-Classless-Static-Route
和DHCP-Site-specific-25
(又名 Microsoft 静态路由)选项来从 Freeradius DHCP 服务器发送无类静态路由。DHCP-Discover
DHCP-Request
但是:如果我将默认网关设置为Strongswan 文档0.0.0.0
建议的那样,Microsoft VPN 客户端似乎不接受静态路由。
至少我在使用route print -4
.
此外,当我0.0.0.0
通过 VPN 接口用作标准网关时,我无法在 Windows 客户端上手动添加路由。
然而:
假设我想192.168.200.0/24
通过 VPN 访问子网,我的 VPN 服务器将地址分配192.168.201.2/24
给我的 Windows 客户端。然后实际上可以通过使用 windows 命令通过 192.168.201.2 访问子网 192.168.200.0/24 来在 windows 客户端创建静态路由:
route add 192.168.200.0 mask 255.255.255.0 192.168.201.2
我知道它看起来有点奇怪,但我可以 ping192.168.200.0
子网上的任何主机,所以只要它有效,我就很高兴。:-)
但是:如果我可以通过从我的 VPN 服务器通告路由而不是在所有 VPN 客户端上手动进行,我会更高兴。:-)
这意味着我必须对 Freeradius 中的 DHCP 配置进行一些动态编程。在我的情况下,这意味着我必须在 DHCP-Discover 和 DHCP-request 中引用 perl 模块,该模块获取分配的客户端 vpn ip 地址,将其转换为八位字节并将其与也以八位字节形式给出的静态路由组合。
一个例子:
子网192.168.200.0/24
将被编码为0x18c0a8c8
首先编码子网掩码。
客户端192.168.201.2/24
将被编码,0xc0a8c902
因为它只是将 IP 地址中的每个数字转换为十六进制。
路由的最终编码将是:0x18c0a8c8c0a8c902
因为它只是两个字符串的连接。
然后我必须使用update reply
以下代码:
update reply {
&DHCP-Classless-Static-Route = 0x18c0a8c8c0a8c902
&DHCP-Site-specific-25 = 0x18c0a8c8c0a8c902
}
如果还有更多路由,则所有路由将连接成一个长字符串。
棘手的部分:
假设您具有freeradius/3.0/sites-available/dhcp
文件中的 Freeradius DHCP 服务器的默认配置。
DHCP-Discover 和 DHCP-Request 文件的一般结构如下:
dhcp DHCP-Request {
update reply {
&DHCP-Message-Type = DHCP-Ack
}
update reply {
# General DHCP options, such as default GW, DNS, IP-address lease time etc.
}
update control {
&Pool-Name := "vpn_pool"
}
dhcp_sqlippool
ok
}
然后据我所知,我需要在dhcp_sqlippool
被调用之后和返回之前调用我的 perl 模块ok
,因为dhcp_sqlippool
它是将 ipaddress 分配给 VPN 客户端的模块。
这意味着我的版本将类似于:
dhcp DHCP-Request {
update reply {
&DHCP-Message-Type = DHCP-Ack
}
update reply {
# General DHCP options, such as default GW, DNS, IP-address lease time etc.
}
update control {
&Pool-Name := "vpn_pool"
}
dhcp_sqlippool
perl
# If perl module returned no error
if(ok) {
update reply {
# Perl-Route contains a hex encoded string with all routes.
&DHCP-Classless-Static-Route = Perl-Route
&DHCP-Site-specific-25 = Perl-Route
}
}
# Not sure if this one is needed?
update reply {
&DHCP-End-Of-Options = 255
}
ok
}
为了使其工作,我必须在freeradius/3.0/mods-enabled
文件夹下启用 perl 并修改文件名以freeradius/3.0/mods-enabled/perl
将其指向我的 perl 模块。比如:
filename = ${modconfdir}/${.:instance}/dhcp/Options.pm
但是我如何以正确的方式引用对 perl 的调用呢?
我以为我必须启用该行并在我的 perl 模块func_post_auth = post_auth
中freeradius/3.0/mods-enabled/perl
创建一个sub post_auth
部分来处理来自 Freeradius 的调用,但据我在日志中看到的,我在 Freeradius 中收到以下错误:
(8) perl: perl_embed:: module = /etc/freeradius/3.0/mods-config/perl/dhcp/Options.pm ,
func = post_auth exit status= Undefined subroutine &main::post_auth called.
...
(8) [perl] = fail
(8) } # dhcp DHCP-Discover = fail
那么我没有看到的是什么?
我把头撞在墙上几次,但至少我让 perl 模块工作,虽然我并不完全是我想要的,因为通过 DHCP 的静态路由不会从 Freeradius DHCP 服务器通过 Strongswan 传递到 VPN 客户端,但从 Freeradius DHCP 服务器调试 UDP 包意味着问题出在其他地方。
无论如何,这就是我所做的:
freeradius/3.0/mods-enabled
并至少设置以下几行:freeradius/3.0/sites-enabled/dhcp
相关的地方是DHCP-Discover
和DHCP-Request
:freeradius/3.0/mods-config/perl/dhcp/Options.pm
:可以从这里调整 perl 代码,因此根据客户端操作系统发送选项 121或选项 249。
我还保留了使代码更通用的可能性,因此静态路由可以直接在 Freeradius 配置文件中定义给读者。