Saturday, August 29, 2015

Openconnect Server (ocserv) on Openwrt

I'd like to set up a VPN server on a router running Openwrt. There are several choices, L2TP, PPTP, OpenVPN and openconnect. PPTP is not very secure. L2TP must be used with IPSec for security. While OpenVPN and openconnect are both SSL-VPN. They are easy to configure and adaptive to the restrictions of ISP. Because there is a luci app for openconnect server. It's easier to set up than OpenVPN. I would set up an openconnect server, which operates in pseudo-bridge mode, meaning remote clients are on the same subnet as the computers at home.


Firstly, run opkg update, and then opkg install ocserv luci-app-ocserv.

To enable proxy ARP, add net.ipv4.conf.all.proxy_arp=1 to /etc/sysctl.conf

Then add the following to /etc/firewall.user, in order to enable forwarding for VPN traffic.
iptables -A input_rule -i vpns+ -j ACCEPT
iptables -A forwarding_rule -i vpns+ -j ACCEPT
iptables -A forwarding_rule -o vpns+ -j ACCEPT
iptables -A output_rule -o vpns+ -j ACCEPT

You can configure ocserv via luci, where you can change the listening port, IP assignment range and add users. You should calculate IP address and netmask to avoid collision with other LAN clients.

You should also open ocserv's listening port, in my case 443, in firewall, allowing TCP and UDP.

Now, reboot the router and then enable ocserv in luci. Wait for a while and then you can see the auto-generated CA certificate. Import it into the clients. And now you can connect to the openconnect server.


I found the luci script for showing connected users in the overview page is buggy. The user list is always empty. So I modified some code. Because I am not familiar with lua language. The code is not elegant. But it works.

The file to change is /usr/lib/lua/luci/controller/ocserv.lua

find the the function ocserv_status(), replace it with the following

function ocserv_status()
local ipt = io.popen("/usr/bin/occtl show users");

if ipt then
ipt:read("*l")
local fwd = { }
while true do

local ln = ipt:read("*l")
if not ln then break end

local arr, pos = {}, 1
for k in ln:gmatch("%S+") do
arr[pos] = k
pos = pos + 1
end
if pos > 9 then
fwd[#fwd+1] = {
id = arr[1],
user = arr[2],
group = arr[3],
vpn_ip = arr[4],
ip = arr[5],
device = arr[6],
time = arr[7],
cipher = arr[8],
status = arr[9]
}
end
end
ipt:close()
luci.http.prepare_content("application/json")
luci.http.write_json(fwd)
end
end


Links:

https://github.com/openconnect/recipes/blob/master/ocserv-pseudo-bridge.md
http://wiki.openwrt.org/doc/howto/openconnect-setup

No comments:

Post a Comment