小型办公室服务
摘要:本文档将概述如何使用 Linux 容器化 (LXC) 为小型远程办公室提供各种网络服务。它旨在作为 DMVPN 辐条节点的补充。
除了 DMVPN 网络提供的办公室之间加密通信外,还将提供以下服务
- 带有域过滤的 Internet 浏览代理服务器(受保护内部网络上的有线客户端)
- 用于 wifi 客户端的独立代理
- SIP 电话系统,包括基于 Web 的配置和基本语音邮件服务
假设使用以下 VLAN 和子网,与 DMVPN 文档相同
接口 | 描述 | 子网 |
---|---|---|
bond0.3 | 管理 | 10.1.0.129/26 |
bond0.101 | 局域网 | 10.1.0.0/25 |
bond0.256 | 来自 ISP1 的互联网 | 从 ISP 分配 |
bond0.257 | 来自 ISP2 的互联网 | 从 ISP 分配 |
bond0.620 | wifi 代理和 dmvpn 辐条节点之间的传输 | 10.1.0.252/30 |
bond0.701 | WiFi 客户端(无法访问 DMVPN 网络) | 172.17.48.0/24 |
bond0.1101 | 语音 | 10.2.0.0/24 |
硬件
对于服务少于 20 人的办公室,以下容器可以轻松运行在低功耗硬件上,例如 Via Nano 1.6Ghz Jetway 板,配备 8GB RAM 和双 500GB SATA 硬盘,以 RAID 1(软件)运行。
设置 LXC 主机
启动 Alpine USB
按照 创建可引导设备 中的说明操作。
Alpine 设置
setup-alpine
您将看到类似这样的提示... | 关于您可以输入内容的建议... |
---|---|
选择键盘布局 [none]
|
输入适合您的布局 |
选择变体
|
输入适合您的布局(如果提示) |
输入系统主机名(短格式,例如“foo”)[localhost]
|
输入主机名,例如 lxc-host |
可用接口为:eth0
|
输入 bond0.3 |
可用的绑定从属设备为:eth0 eth1
|
eth0 eth1 |
bond0 的 IP 地址?(或“dhcp”、“none”、“?”)[dhcp]
|
按 Enter 键确认“none” |
bond0.3 的 IP 地址?(或“dhcp”、“none”、“?”)[dhcp]
|
<%LXCHOST_MANAGEMENT_IP_ADDRESS%> |
子网掩码?[255.255.255.0]
|
<%DMVPN_MANAGEMENT_NETMASK%> |
网关?(或“none”)[none]
|
<%DMVPN_MANAGEMENT_NET_IP%> |
您是否要执行任何手动网络配置?[no]
|
no |
DNS 域名?(例如“bar.com”)[]
|
输入您内网的域名,例如, office.example.net |
DNS 名称服务器?[]
|
8.8.8.8 8.8.4.4 (我们稍后会更改它们) |
正在更改 root 密码
|
为控制台输入安全密码 |
重新输入密码
|
重新输入上述密码 |
您所在的时区是?(“?”查看列表)[UTC]
|
按 Enter 键确认“UTC” |
HTTP/FTP 代理 URL?(例如“http://proxy:8080”,或“none”)[none]
|
http://<%DMVPN_LAN_IP%>:8080 |
输入镜像编号 (1-9) 或要添加的 URL(或 r/f/e/done)[f]
|
选择离您较近的镜像并按 Enter 键 |
哪个 SSH 服务器?(“openssh”、“dropbear”或“none”)[openssh]
|
按 Enter 键确认“openssh” |
要运行哪个 NTP 客户端?(“openntpd”、“chrony”或“none”)[chrony]
|
按 Enter 键确认“chrony” |
您想使用哪些磁盘?(或“?”查看帮助或“none”)[none]
|
sda sdb |
您想如何使用它们?(“sys”、“data”或“?”查看帮助)
|
data |
输入存储配置的位置(“floppy”、“usb”或“none”)[usb]
|
按 Enter 键确认“usb” |
输入 apk 缓存目录(或“?”或“none”)[/media/usb/cache]
|
按 Enter 键确认“/media/usb/cache” |
升级软件包
apk update apk upgrade
保存更改
lbu commit
完成设置并重启
reboot
设置网络
使用您喜欢的编辑器配置 /etc/network/interfaces
内容为/etc/network/interfaces
通过重启网络应用更改
rc-service networking restart
启用 IP 转发
echo "1" > /proc/sys/net/ipv4/ip_forward
设置防火墙
apk add acf-awall
使用您喜欢的编辑器,为防火墙创建基本策略
内容为/etc/awall/optional/base.json
激活防火墙,并允许 iptables 在启动时自动启动
modprobe ip_tables awall enable base awall activate -f rc-update add iptables
安装 LXC
安装 LXC 和 Bridge 软件包
apk add lxc bridge
使用您喜欢的编辑器配置 /etc/lxc/default.conf
内容为/etc/lxc/default.conf
完成安装
lbu ci reboot
安装 Web 代理容器
创建和配置容器
lxc-create -n webproxy -f /etc/lxc/default.conf -t alpine
创建启动脚本
ln -s lxc /etc/init.d/lxc.webproxy
编辑容器的配置文件,位于 /var/lib/lxc/webproxy/config,以反映 Web 代理容器的网络
内容为/var/lib/lxc/webproxy/config
启动容器
rc-service lxc.webproxy start
配置容器自动启动
rc-update add lxc.webproxy
进入 webproxy 容器
lxc-console -n webproxy
以 root 身份登录
删除过时的 /etc/network/interfaces
rm /etc/network/interfaces
创建并配置新的 /etc/network/interfaces,如下所示
内容为/etc/network/interfaces
启动网络
rc-service networking start
将规则添加到 DMVPN awall 策略,以允许此代理访问互联网
内容为 /etc/awall/optional/internet-host.json
配置远程管理
apk update setup-sshd -c openssh sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
启动 ssh
rc-service sshd start
为容器配置密码
passwd
设置 acf 以进行 Web 管理
setup-acf
设置防火墙
apk add acf-awall
使用您喜欢的编辑器,为防火墙创建策略
内容为/etc/awall/optional/base.json
内容为/etc/awall/optional/webproxy.json
激活防火墙,并允许 iptables 在启动时自动启动
awall enable base awall enable webproxy awall activate -f rc-update add iptables
安装和配置 Squid Web 代理服务
安装所需的软件包
apk add acf-squid squark acf-lighttpd
配置 /etc/squid/squid.conf,替换 <%WEBPROXY_IP_ADDRESS%>、<%HOSTNAME%> 和 <%DOMAIN%>
内容为/etc/squid/squid.conf
#Squid config for webproxy # This port listens for client requests http_port 8080 visible_hostname <%HOSTNAME%>.<%DOMAIN%> cache_mem 8 MB # If you don't have an HD installed comment the "cache_dir" line below cache_dir aufs /var/cache/squid 900 16 256 # Even though we only use one proxy, this line is recommended # More info: http://www.squid-cache.org/Versions/v2/2.7/cfgman/hierarchy_stoplist.html hierarchy_stoplist cgi-bin ? # Keep 7 days of access logs logfile_rotate 7 logformat squark %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt %rG access_log /var/log/squid/access.log squark cache_store_log none pid_filename /var/run/squid.pid # Make sure client IP is passed to Squark log_uses_indirect_client on acl_uses_indirect_client on # Fix for problems with branch file transfer application # ignore_expect_100 on (deprecated) # Debugging Squid, see http://wiki.squid-cache.org/KnowledgeBase/DebugSections # for more info # Keep 7 days of cache log debug_options rotate=7 # Web auditors want to see the full uri, even with the query terms strip_query_terms off refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern . 0 20% 4320 coredump_dir /var/cache/squid # # Authentication # # # Access Control Lists (ACL's) # # Standard ACL settings acl QUERY urlpath_regex cgi-bin \? asp aspx jsp acl to_localhost dst <%WEBPROXY_IP_ADDRESS%> acl SSL_ports port 443 563 8004 9000 acl Safe_ports port 21 70 80 81 210 280 443 563 499 591 777 1024 1022 1025-65535 acl purge method PURGE acl CONNECT method CONNECT # Squark filter url_rewrite_program /usr/bin/squark-filter url_rewrite_children 1 concurrency=128 # Require authentication acl userlist src all # Definition of zones acl Zone_B src <%LAN_SUBNET%>/<%LAN_SLASH_NOTATION%> #acl Zone_D src <%WiFi_SUBNET%>/<%WiFi_SLASH_NOTATION%> # Settings migrated from smn acl Zone_B_AllowedUserDomains dstdomain "/etc/squid/alloweduserdomains" acl Zone_B_AllowedServicesHosts src "/etc/squid/allowedserviceshosts" acl Zone_B_AllowedServicesDomains dstdomain "/etc/squid/allowedservicesdomains" # Settings migrated from services acl AnonBrowsers browser "/etc/squid/anonbrowserlist" acl AnonIPAddrs src "/etc/squid/anoniplist" acl AnonDomain url_regex "/etc/squid/anondomainlist" # # Access restrictions # cache deny QUERY # Only allow cachemgr access from localhost http_access allow manager localhost http_access deny manager # Only allow purge requests from localhost http_access allow purge localhost http_access deny purge # Deny requests to unknown ports http_access deny !Safe_ports # Deny CONNECT to other than SSL ports http_access deny CONNECT !SSL_ports # Allow hosts in Zone_B and Zone_C to access hosts listed in # /etc/squid/alloweduserdomains http_access allow Zone_B Zone_B_AllowedUserDomains # Allow hosts listed in /etc/squid/allowedserviceshosts to # access domains listed in /etc/squid/allowedservicesdomains http_access allow Zone_B_AllowedServicesHosts Zone_B_AllowedServicesDomains # Denying all access not explictly allowed http_access deny all ##Squark URL rewriter #Prevent squark from filtering itself url_rewrite_access deny manager url_rewrite_access deny to_localhost #We do not want authentication for these sites: url_rewrite_access deny Zone_B Zone_B_AllowedUserDomains url_rewrite_access deny Zone_B Zone_B_AllowedServicesDomains http_reply_access allow all icp_access allow all
配置 /etc/lighttpd/lighttpd.conf,替换 <%WEBPROXY_IP_ADDRESS%>
内容为/etc/lighttpd/lighttpd.conf
############################################################################## # Default lighttpd.conf for Gentoo. # $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/lighttpd.conf,v 1.3 2005/09/01 14:22:35 ka0ttic Exp $ ############################################################################### var.basedir = "/var/www/localhost" var.logdir = "/var/log/lighttpd" var.statedir = "/var/lib/lighttpd" server.modules = ( "mod_access", "mod_accesslog", "mod_extforward" ) include "mime-types.conf" include "mod_cgi.conf" server.username = "lighttpd" server.groupname = "lighttpd" server.document-root = var.basedir + "/squark" server.pid-file = "/var/run/lighttpd.pid" server.errorlog = var.logdir + "/error.log" server.indexfiles = ("index.php", "index.html", "index.htm", "default.htm") server.follow-symlink = "enable" static-file.exclude-extensions = (".php", ".pl", ".cgi", ".fcgi") accesslog.filename = var.logdir + "/access.log" url.access-deny = ("~", ".inc") extforward.forwarder = ("<%WEBPROXY_IP_ADDRESS%>" => "trust")
配置 mod_cgi.conf
内容为/etc/lighttpd/mod_cgi.conf
############################################################################### # mod_cgi.conf # include'd by lighttpd.conf. # $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_cgi.conf,v 1.1 2005/08/27 12:36:13 ka0ttic Exp $ ############################################################################### # # see cgi.txt for more information on using mod_cgi # server.modules += ("mod_cgi") # NOTE: this requires mod_alias alias.url = ( "/cgi-bin/" => var.basedir + "/cgi-bin/" ) # # Note that you'll also want to enable the # cgi-bin alias via mod_alias (above). # $HTTP["url"] =~ "^/cgi-bin/" { # disable directory listings dir-listing.activate = "disable" # only allow cgi's in this directory cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "/usr/bin/haserl" ) }
将 Squark 网页链接到 Web 服务器主目录
ln -s /usr/share/squark/www/ /var/www/localhost/squark
创建 Squark 组
addgroup squark
将“squid”和“lighttpd”用户设为 squark 组的成员
addgroup squid squark addgroup lighttpd squark
启动 lighttpd,并配置该服务在容器启动时启动
rc-service lighttpd start rc-update add lighttpd
启动 Squid,并配置为在启动时启动
rc-service squid start rc-update add squid
安装 DHCP 和 DNS 服务器容器
创建和配置容器
lxc-create -n dhcpdns -f /etc/lxc/default.conf -t alpine
创建启动脚本
ln -s lxc /etc/init.d/lxc.dhcpdns
编辑容器的配置文件,位于 /var/lib/lxc/dhcpdns/config,以反映 Web 代理容器的网络
内容为/var/lib/lxc/dhcpdns/config
#Management Network Config lxc.network.type = macvlan lxc.network.macvlan.mode = bridge lxc.network.link = bond0.3 lxc.network.name = eth0 #WiFi Network Config lxc.network.type = macvlan lxc.network.macvlan.mode = bridge lxc.network.link = bond0.701 lxc.network.name = eth1 #Voice Network Config lxc.network.type = macvlan lxc.network.macvlan.mode = bridge lxc.network.link = bond0.1101 lxc.network.name = eth2
启动容器
rc-service lxc.dhcpdns start
配置容器自动启动
rc-update add lxc.dhcpdns
进入 dhcpdns 容器
lxc-console -n dhcpdns
以 root 身份登录
删除过时的 /etc/network/interfaces
rm /etc/network/interfaces
创建并配置新的 /etc/network/interfaces,如下所示
内容为/etc/network/interfaces
启动网络
rc-service networking start
配置和启用代理设置
setup-proxy http://10.1.0.2:8080 . /etc/profile.d/proxy.sh
配置远程管理
apk update setup-sshd -c openssh sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
启动 ssh
rc-service sshd start
为容器配置密码
passwd
设置 acf 以进行 Web 管理
setup-acf
设置防火墙
apk add acf-awall
使用您喜欢的编辑器,为防火墙创建策略
内容为/etc/awall/optional/base.json
内容为/etc/awall/optional/dhcp.json
内容为/etc/awall/optional/dns.json
激活防火墙,并允许 iptables 在启动时自动启动
awall enable base awall enable dhcp awall enable dns awall activate -f rc-update add iptables
安装和配置 DHCP 和 DNS 服务
安装 dhcpd 软件包
apk add acf-dhcp
创建一个新的 dhcpd.conf 文件
内容为/etc/dhcp/dhcpd.conf
## Common settings default-lease-time 302400; max-lease-time 604800; ddns-update-style none; log-facility local7; authoritative; ## Common options option time-servers 10.2.0.1; option boot-server code 66 = string; ## Voice subnet 10.2.0.0 netmask 255.255.255.0 { range "10.2.0.20 10.2.0.250"; option domain-name-servers 10.2.0.2; option routers 10.2.0.1; option boot-server "http://10.2.0.4"; option domain-name "office.example.net"; } ## WiFi subnet 172.17.48.0 netmask 255.255.255.0 { range "172.17.48.10 172.17.48.250"; option routers 172.17.48.1; option domain-name-servers 172.17.48.1; }
启动 DHCP 服务并添加到默认运行级别
rc-service dhcpd start rc-update add dhcpd
安装 nsd 和 unbound 软件包
apk add unbound
删除 unbound.conf
rm /etc/unbound/unbound.conf
使用您喜欢的编辑器为 unbound 创建新配置
内容为/etc/unbound/unbound.conf
启动 Unbound 并允许容器使用它 {{Cmd|rc-service unbound start rc-update add unbound echo nameserver 10.2.0.2 > /etc/resolv.conf
安装 nsd
apk add nsd
配置 nsd 配置
内容为/etc/nsd/nsd.conf
为 nsd 配置区域文件
内容为/etc/nsd/nsd.conf
检查 nsd 配置并启动服务
nsd-checkconf /etc/nsd/nsd.conf rc-service nsd start rc-update add nsd
安装 SIP 容器
创建和配置容器
lxc-create -n sip -f /etc/lxc/default.conf -t alpine
创建启动脚本
ln -s lxc /etc/init.d/lxc.sip
编辑容器的配置文件,位于 /var/lib/lxc/sip/config,以反映 sip 容器的网络
内容为/var/lib/lxc/sip/config
启动容器
/etc/iniit.d/lxc.sip
配置容器自动启动
rc-update add lxc.sip
进入 sip 容器
lxc-console -n sip
以 root 身份登录
删除过时的 /etc/network/interfaces
rm /etc/network/interfaces
创建并配置新的 /etc/network/interfaces,如下所示
内容为/etc/network/interfaces
启动网络
rc-service networking start
配置和启用代理设置
setup-proxy http://10.1.0.2:8080 . /etc/profile.d/proxy.sh
配置远程管理
apk update setup-sshd -c openssh sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
启动 ssh
rc-service sshd start
为容器配置密码
passwd
设置 acf 以进行 Web 管理
setup-acf
设置防火墙
apk add acf-awall
使用您喜欢的编辑器,为防火墙创建策略
内容为/etc/awall/optional/base.json
内容为/etc/awall/optional/sip.json
内容为/etc/awall/optional/syslog.json
激活防火墙,并允许 iptables 在启动时自动启动
awall enable base awall enable sip awall enable syslog awall activate -f rc-update add iptables
安装和配置 Postgresql
安装 postgresql 软件包
apk update apk add acf-postgresql
准备数据库
rc-service postgresql setup
配置 /var/lib/postgresql/9.3/data/postgresql.conf 以将“log_destination”变量设置为显示
内容为/var/lib/postgresql/9.3/data/postresql.conf
启动数据库并配置 postgresql 以在启动时启动
rc-service postgresql start rc-update add postgresql
安装 acf-provisioning
- vi /etc/kamailio/kamctlrc
SIP_DOMAIN=sip.office.example.net DBENGINE=PGSQL DBHOST=127.0.0.1 DBNAME=openser DBRWUSER=openser DBRWPW="openser" DBROUSER=openserro DBROPW=openserro DBROOTUSER="postgres"
- yes | kamdbctl create openser
- apk add acf-provisioning lua-socket lua-expat
- 创建 /etc/provisioning/update_device_params.lua
-- This is the script run after editing device params - basically only worried about extension and password local functions, params, oldparams = ... require("posix") require("luasql.postgres") local root = "/var/www/provisioning/htdocs/" local b62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" APP.logevent("got to update_device_params script") local function generatepw() -- generate a random 12-character alphanumeric string local file = io.open("/dev/urandom") local str = "" if file == nil then return nil end local size = 12 while (size > 0 ) do local offset = (string.byte(file:read(1)) % 62) + 1 str = str .. string.sub (b62, offset, offset) size = size - 1 end return str end local function findip(mac) if not mac or mac == "" then return nil end local ipaddr = functions.getselectresponse("SELECT ip FROM provisioning_requests WHERE mac~*'"..mac.."'") if ipaddr and ipaddr[1] then return ipaddr[1].ip end end local function addfuturenotify(ipaddr, extension) local res, err = pcall(function() functions.runsqlcommand("DELETE FROM notify WHERE ipaddr='"..ipaddr.."' AND extension='"..extension.."'") end) if not res and err then if string.match(err, "relation \"(%S+)\" does not exist") then functions.runsqlcommand("CREATE TABLE notify (ipaddr text, extension text, seasoned boolean DEFAULT false)") else assert(res, err) end end -- if table missing, create it and delete again functions.runsqlcommand("INSERT INTO notify VALUES('"..ipaddr.."', '"..extension.."')") end local notify_device = function(mac, extension) local ipaddr = findip(mac) if ipaddr then APP.logevent("Notifying "..ipaddr.." to update for "..(mac or "")) os.execute("/etc/provisioning/notify_device "..ipaddr.." "..extension) addfuturenotify(ipaddr, extension) else APP.logevent("Warning - could not find IP address for "..(mac or "")) end end local kam = APP:new("kamailio/kamailio") -- A table of devices to notify to update local devices = {} -- First, we check the registration numbers / passwords to 1) set a random password (if necessary) 2) make sure password matches any other registrations to same extension 3) push changes (add / delete / or update) to Kam database -- Because this script also handles when device classes change, we have to consider that extensions are added / removed local regs = {} local forwarding = {"forwardnoanswerenable", "forwardnoanswer", "forwardbusyenable", "forwardbusy", "forwardallenable", "forwardall"} local forwardsettings = {} -- Collect forwarding settings local passwords = {} -- Collect old extension/password pairs for name,val in pairs(params.value) do if not regs[name] and string.match(name, "^reg") then regs[name] = true end end oldparams = oldparams or {value={}} for name,val in pairs(oldparams.value) do if string.match(name, "^reg") then if val.value and val.value.extension and val.value.password then passwords[val.value.extension.value] = val.value.password.value end if val.value and val.value.extension then local fwd = {} for i,f in ipairs(forwarding) do if val.value[f] then fwd[f] = val.value[f].value end end forwardsettings[val.value.extension.value] = fwd end if not regs[name] then regs[name] = true end end end local extension_id = params.value.reg1.value.extension.param_id local password_id = params.value.reg1.value.password.param_id functions.runsqlcommand("BEGIN TRANSACTION") for name,val in pairs(regs) do local new = "" local old = "" if params.value[name] then new = params.value[name].value.extension.value end if oldparams.value[name] then old = oldparams.value[name].value.extension.value end if new ~= old then -- Extension changed -- First, let's remove the stuff for the old extension if old ~= "" then local others = functions.getselectresponse("SELECT count(*) FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..old.."'") if others[1].count == "0" then APP.logevent("Removing old registration "..old) -- remove the registration kam.model.delete_user(old) end end -- Now, add the new extension if new ~= "" then local pass if params.value[name].value.password.value ~= "" and (not oldparams.value[name] or (oldparams.value[name].value.password.value ~= params.value[name].value.password.value)) then -- The password parameter was changed and not blank, so use it pass = params.value[name].value.password.value APP.logevent("Added a new registration "..new.." with specified password "..pass) -- There may be other devices with this extension local others = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id=(SELECT param_id FROM provisioning_params WHERE name='mac') AND device_id IN (SELECT device_id FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") for i,o in ipairs(others) do -- We'll notify whether it changed or not devices[o.value] = new end elseif passwords[new] then pass = passwords[new] APP.logevent("Added a new registration "..new.." with reused password "..pass) else local others = functions.getselectresponse("SELECT * FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."' AND device_id!='"..params.value.device_id.value.."'") -- If this is a new registration, use a new password if #others == 0 then pass = generatepw() APP.logevent("Added a new registration "..new.." with random password "..pass) else -- Use the old password local p = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id='"..password_id.."' AND device_id='"..others[1].device_id.."' AND group_name='"..others[1].group_name.."' LIMIT 1") pass = p[1].value APP.logevent("Added a new registration "..new.." with reused password "..pass) end end passwords[new] = pass params.value[name].value.password.value = pass functions.runsqlcommand("DELETE FROM provisioning_values WHERE param_id='"..password_id.."' AND (device_id, group_name) IN (SELECT device_id, group_name FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") functions.runsqlcommand("INSERT INTO provisioning_values (SELECT device_id, group_name, '"..password_id.."', '"..pass.."' FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") local u = kam.model.get_user(new) if u.value.username.errtxt then -- Add this registration to Kam local u = kam.model.get_new_user() u.value.username.value = new u.value.password.value = pass u.value.password_confirm.value = pass kam.model.create_new_user(u) else u.value.password.value = pass u.value.password_confirm.value = pass kam.model.update_user(u) end -- Let's also look at the forwarding settings local change = false local supported = false local fwd = {} for i,f in ipairs(forwarding) do if params.value[name].value[f] then supported = true fwd[f] = params.value[name].value[f].value if ((not oldparams.value[name] or not oldparams.value[name].value[f]) and (params.value[name].value[f].value ~= params.value[name].value[f].default)) or (oldparams.value[name] and oldparams.value[name].value[f] and (params.value[name].value[f].value ~= oldparams.value[name].value[f].value)) then change = true end end if change then local others = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id=(SELECT param_id FROM provisioning_params WHERE name='mac') AND device_id IN (SELECT device_id FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") for i,o in ipairs(others) do -- We'll notify whether it changed or not devices[o.value] = new end end end if supported then if not change and forwardsettings[new] then fwd = forwardsettings[new] elseif not change then -- This is a new extension, and the forwarding has not been set. We should check to see if there are any other devices with this extension local others = functions.getselectresponse("SELECT * FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."' AND device_id!='"..params.value.device_id.value.."'") if #others > 0 then -- Use the existing settings for i,f in ipairs(forwarding) do local v = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id='"..params.value[name].value[f].param_id.."' AND device_id='"..others[1].device_id.."' AND group_name='"..others[1].group_name.."' LIMIT 1") if #v > 0 then fwd[f] = v[1].value else fwd[f] = params.value[name].value[f].default end end end end if not change then for i,f in ipairs(forwarding) do params.value[name].value[f].value = fwd[f] end end forwardsettings[new] = fwd for i,f in ipairs(forwarding) do functions.runsqlcommand("DELETE FROM provisioning_values WHERE param_id='"..params.value[name].value[f].param_id.."' AND (device_id, group_name) IN (SELECT device_id, group_name FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") if fwd[f] ~= params.value[name].value[f].default then functions.runsqlcommand("INSERT INTO provisioning_values (SELECT device_id, group_name, '"..params.value[name].value[f].param_id.."', '"..tostring(fwd[f]).."' FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") end end end end elseif params.value[name] and oldparams.value[name] and params.value[name].value.extension.value ~= "" then if params.value[name].value.password.value ~= oldparams.value[name].value.password.value then -- Password changed - make any other registrations to this extension also change local pass = params.value[name].value.password.value if pass and pass ~= "" then APP.logevent("Password changed for "..new.." from "..oldparams.value[name].value.password.value.." to "..pass) else pass = generatepw() APP.logevent("Password cleared for "..new..", so set new random password "..pass) end passwords[new] = pass functions.runsqlcommand("DELETE FROM provisioning_values WHERE param_id='"..password_id.."' AND (device_id, group_name) IN (SELECT device_id, group_name FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") functions.runsqlcommand("INSERT INTO provisioning_values (SELECT device_id, group_name, '"..password_id.."', '"..pass.."' FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") local u = kam.model.get_user(new) u.value.password.value = params.value[name].value.password.value u.value.password_confirm.value = params.value[name].value.password.value kam.model.update_user(u) -- Have to notify those other devices too local others = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id=(SELECT param_id FROM provisioning_params WHERE name='mac') AND device_id IN (SELECT device_id FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") for i,o in ipairs(others) do devices[o.value] = new end end local change = false local fwd = {} for i,f in ipairs(forwarding) do if params.value[name].value[f] and (not oldparams.value[name].value[f] or params.value[name].value[f].value ~= oldparams.value[name].value[f].value) then change = true break end end if change then -- Forwarding settings changed - make any other registrations to this extension also change for i,f in ipairs(forwarding) do functions.runsqlcommand("DELETE FROM provisioning_values WHERE param_id='"..params.value[name].value[f].param_id.."' AND (device_id, group_name) IN (SELECT device_id, group_name FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") if params.value[name].value[f].value ~= params.value[name].value[f].default then functions.runsqlcommand("INSERT INTO provisioning_values (SELECT device_id, group_name, '"..params.value[name].value[f].param_id.."', '"..tostring(params.value[name].value[f].value).."' FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") end end -- Have to notify those other devices too local others = functions.getselectresponse("SELECT value FROM provisioning_values WHERE param_id=(SELECT param_id FROM provisioning_params WHERE name='mac') AND device_id IN (SELECT device_id FROM provisioning_values WHERE param_id='"..extension_id.."' AND value='"..new.."')") for i,o in ipairs(others) do devices[o.value] = new end end end end functions.runsqlcommand("COMMIT") -- If reg1 or freepstn changed, then need to change free-pstn in kam -- Since there can be multiple devices with the same reg1, we can't rely on params and oldparams -- Check both reg's --APP.logevent(session.serialize("params", params)) local reg = {} if oldparams.value.reg1 and oldparams.value.reg1.value.extension and oldparams.value.reg1.value.extension.value ~= "" then reg[oldparams.value.reg1.value.extension.value] = false end if params.value.reg1 and params.value.reg1.value.extension and params.value.reg1.value.extension.value ~= "" then local pstn = false if params.value.routing and params.value.routing.value.freepstn then pstn = params.value.routing.value.freepstn.value end reg[params.value.reg1.value.extension.value] = pstn end APP.logevent("Looking at free-pstn") for r,f in pairs(reg) do -- if we're not sure, check provisioning database if not f then -- Most devices will have free-pstn due to class-of-service, but can be overridden, so this can get tricky -- Check all devices where reg1 extension = r, and see what the freepstn value is for each local others = functions.getselectresponse("SELECT CASE WHEN v.value IS NOT NULL THEN v.value WHEN g2p.value IS NOT NULL THEN g2p.value ELSE p.value END AS value ".. "FROM (devices_to_classes d2t JOIN provisioning_classes t USING(class_id) JOIN classes_to_param_groups t2g USING (class_id) JOIN provisioning_groups g USING(group_id) ".. "JOIN param_groups_to_params g2p USING(group_id) JOIN provisioning_params p USING(param_id)) LEFT JOIN provisioning_values v ON (d2t.device_id=v.device_id AND p.param_id=v.param_id AND g.name=v.group_name ) ".. "WHERE p.name='freepstn' AND d2t.device_id IN (SELECT device_id FROM provisioning_values WHERE param_id='"..extension_id.."' AND group_name='reg1' AND value='"..r.."')") for i,o in ipairs(others) do -- Now check the freepstn value for each one if o.value == "true" then f = true break end end end -- Now, check the Kamailio group table local alreadythere = false local entries = kam.model.list_table_entries("grp") for i,e in ipairs(entries.value.entries.value) do if e.username == r then alreadythere = true if not f then APP.logevent("Removing free-pstn for "..r) -- Remove free-pstn from the old extension kam.model.delete_table_entry("grp", e.id) end break end end if f and not alreadythere then APP.logevent("Adding free-pstn for "..r) -- Add free-pstn to the new extension local e = kam.model.get_table_entry("grp") e.value.username.value = r e.value.domain.value = "" e.value.grp.value = "free-pstn" e.value.last_modified.value = os.date("%c") kam.model.create_table_entry(e) end end kam:destroy() -- If the mac address changed for Polycom with valid MAC (not blank or all 0's), we need to move the associated config files if oldparams.value.device and oldparams.value.device.value.mac and oldparams.value.device.value.mac.value ~= "" and params.value.device and params.value.device.value.mac and params.value.device.value.mac.value ~= oldparams.value.device.value.mac.value then if string.match(oldparams.value.device.label, "Polycom") and string.match(oldparams.value.device.value.mac.value, "[1-9A-F]") then local deletefiles = true if string.match(params.value.device.value.mac.value, "[1-9A-F]") then --APP.logevent("Moving files for "..oldparams.value.device.value.mac.value) deletefiles = false else --APP.logevent("Deleting files for "..oldparams.value.device.value.mac.value) end local path = root.."Polycom/" if posix.stat(path, "type") == "directory" then for d in posix.files(path) do if string.match(d, string.lower(oldparams.value.device.value.mac.value)) and posix.stat(path..d, "type") == "regular" then local newfile = string.gsub(d, string.lower(oldparams.value.device.value.mac.value), string.lower(params.value.device.value.mac.value)) if deletefiles then --APP.logevent("deleting "..path..d) os.remove(path..d) else --APP.logevent("moving "..path..d.." to "..path..newfile) os.rename(path..d, path..newfile) end end end end end end -- Then, notify the phone to pull it's config -- Try to get a valid extension currently on the device local oldexten = "" for name,val in pairs(oldparams.value) do if string.match(name, "^reg") and val.value.extension and val.value.extension.value ~= "" then oldexten = val.value.extension.value break end end if params.value.device and params.value.device.value.mac and params.value.device.value.mac.value ~= "" then devices[params.value.device.value.mac.value] = oldexten end if oldparams.value.device and oldparams.value.device.value.mac and oldparams.value.device.value.mac.value ~= "" then devices[oldparams.value.device.value.mac.value] = oldexten end for name,value in pairs(devices) do notify_device(name,value) end
- 创建 /etc/provisioning/provisioning_db_script
#!/usr/bin/lua local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " local creation_script = { -- Parameters "INSERT INTO provisioning_params VALUES(default, 'freepstn', 'boolean', 'Free PSTN Access', '', 'false', '200', '')", -- Parameter Groups "INSERT INTO provisioning_groups VALUES(default, 'routing', 'Free PSTN Access', '31')", "INSERT INTO provisioning_groups VALUES(default, 'routing', 'No Free PSTN Access', '32')", -- param_groups_to_params (group_id, param_id, value, editable) "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='Free PSTN Access'), (SELECT param_id FROM provisioning_params WHERE name='freepstn'), 'true', false)", "INSERT INTO param_groups_to_params VALUES((SELECT group_id FROM provisioning_groups WHERE label='No Free PSTN Access'), (SELECT param_id FROM provisioning_params WHERE name='freepstn'), 'false', false)", -- Classes -- provisioning_class_groups (class_group_id, name, label, seq) "INSERT INTO provisioning_class_groups VALUES(default, 'routing', 'Routing', '3')", -- provisioning_classes (class_id, class_group_id, label, seq) "INSERT INTO provisioning_classes VALUES(default, (SELECT class_group_id FROM provisioning_class_groups WHERE name='routing'), 'Free PSTN Access', '1')", "INSERT INTO provisioning_classes VALUES(default, (SELECT class_group_id FROM provisioning_class_groups WHERE name='routing'), 'No Free PSTN Access', '2')", -- classes_to_param_groups (class_id, group_id) "INSERT INTO classes_to_param_groups VALUES((SELECT class_id FROM provisioning_classes WHERE label='Free PSTN Access'), (SELECT group_id FROM provisioning_groups WHERE label='Free PSTN Access'))", "INSERT INTO classes_to_param_groups VALUES((SELECT class_id FROM provisioning_classes WHERE label='No Free PSTN Access'), (SELECT group_id FROM provisioning_groups WHERE label='No Free PSTN Access'))", -- provisioning_options "INSERT INTO provisioning_options VALUES((SELECT param_id FROM provisioning_params WHERE name='polycomringtone'), 'Warble', '15', '15')", "INSERT INTO provisioning_options VALUES((SELECT param_id FROM provisioning_params WHERE name='polycomringtone'), 'Analog Ring', '16', '16')", } local f = io.popen("/usr/share/acf/www/cgi-bin/cli /provisioning/provisioning/getdevicevalues") print(f:read("*a")) f:close() for i,c in ipairs(creation_script) do print(path..'psql -U postgres -c "'..c..'" provisioning 2>&1') local f = io.popen(path..'psql -U postgres -c "'..c..'" provisioning 2>&1') print(f:read("*a")) f:close() end
- chmod 755 /etc/provisioning/provisioning_db_script
- /etc/provisioning/provisioning_db_script
- echo '* * * * * run-parts /etc/periodic/1min' >> /etc/crontabs/root
- mkdir /etc/periodic/1min/
- /etc/periodic/1min/notify_device
#!/usr/bin/lua -- Load libraries require("luasql.postgres") -- Set variables local DatabaseName = "provisioning" local DatabaseUser = "postgres" local DatabasePassword local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin " local env local con -- ################################################################################ -- LOCAL FUNCTIONS local function assert (v, m) if not v then m = m or "Assertion failed!" error(m, 0) end return v, m end -- Escape special characters in sql statements local escape = function(sql) sql = sql or "" sql = string.gsub(sql, "'", "''") return string.gsub(sql, "\\", "\\\\") end local databaseconnect = function() if not con then -- create environment object env = assert (luasql.postgres()) -- connect to data source local err con, err = assert(env:connect(DatabaseName, DatabaseUser, DatabasePassword)) return true end return false end local databasedisconnect = function() if env then env:close() env = nil end if con then con:close() con = nil end end local getselectresponse = function(sql) local retval = {} local cur = assert (con:execute(sql)) local row = cur:fetch ({}, "a") while row do local tmp = {} for name,val in pairs(row) do tmp[name] = val end retval[#retval + 1] = tmp row = cur:fetch (row, "a") end cur:close() return retval end databaseconnect() -- First, let's notify for the seasoned requests local reqs = getselectresponse("SELECT * FROM notify WHERE seasoned='true'") for i,r in ipairs(reqs) do os.execute("/etc/provisioning/notify_device "..r.ipaddr.." "..r.extension) end -- Then mark any others as seasoned assert(con:execute("DELETE FROM notify WHERE seasoned='true'")) assert(con:execute("UPDATE notify SET seasoned='true' WHERE seasoned='false'")) databasedisconnect()
- apk add lighttpd
- rm /etc/lighttpd/lighttpd.conf
- ln -s /etc/provisioning/lighttpd.sample.conf /etc/lighttpd/lighttpd.conf
- /etc/lighttpd/mod_cgi.conf
############################################################################### # mod_cgi.conf # include'd by lighttpd.conf. # $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_cgi.conf,v 1.1 2005/08/27 12:36:13 ka0ttic Exp $ ############################################################################### # # see cgi.txt for more information on using mod_cgi # server.modules += ("mod_cgi") # NOTE: this requires mod_alias alias.url = ( "/cgi-bin/" => var.basedir + "/cgi-bin/" ) # # Note that you'll also want to enable the # cgi-bin alias via mod_alias (above). # $HTTP["url"] =~ "^/cgi-bin/" { # disable directory listings dir-listing.activate = "disable" # only allow cgi's in this directory cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "", "" => "" ) } # vim: set ft=conf foldmethod=marker et :
- rc-service lighttpd start
- rc-update add lighttpd
- 自定义配置
Parameter Default Value registrar IP address or host name of SIP Router(s) digitmap Digit map for your phone system (See Polycom Digit Map Reference) digitmaptimeout Timeout in seconds corresponding to digitmap sntpserver 10.2.0.1 (DMVPN spoke node) timezone Timezone information for this location - see below musiconhold SIP uri of the music-on-hold service - moh@media.office.example.net adminpassword Administration password for advanced settings on phone (on-screen and web interface)
- apk fetch --stdout acf-provisioning-polycom | tar -C / -zx
- 创建一个测试 Polycom 设备并在语音网络中启动它,以验证它是否工作
安装 Kamailio
- apk add kamailio kamailio-presence kamailio-pcre kamailio-postgres
- rc-service kamailio start
- rc-update add kamailio
- FUTURE: POST CONFIG THAT USES SUBSCRIBER TABLE FOR AUTH
安装 SIP 媒体容器
创建和配置容器
lxc-create -n sipmedia -f /etc/lxc/default.conf -t alpine
创建启动脚本
ln -s lxc /etc/init.d/lxc.sipmedia
编辑容器的配置文件,位于 /var/lib/lxc/sipmedia/config,以反映 SIP 媒体容器的网络
内容为/var/lib/lxc/sipmedia/config
启动容器
rc-service lxc.sipmedia
配置容器自动启动
rc-update add lxc.sipmedia
进入 SIP 媒体容器
lxc-console -n sipmedia
以 root 身份登录
删除过时的 /etc/network/interfaces
rm /etc/network/interfaces
创建并配置新的 /etc/network/interfaces,如下所示
内容为/etc/network/interfaces
启动网络
rc-service networking start
配置和启用代理设置
setup-proxy http://10.1.0.2:8080 . /etc/profile.d/proxy.sh
配置远程管理
apk update setup-sshd -c openssh sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
启动 ssh
rc-service sshd start
为容器配置密码
passwd
设置 acf 以进行 Web 管理
setup-acf
设置防火墙
apk add acf-awall
使用您喜欢的编辑器,为防火墙创建策略
内容为/etc/awall/optional/base.json
内容为/etc/awall/optional/sip-track.json
启用和激活防火墙策略,并配置 iptables 在启动时启动
awall enable base awall enable sip-track awall activate -f rc-update add iptables
安装和配置 Freeswitch
安装软件包
安装 Freeswitch 软件包
配置 /etc/freeswitch/freeswitch.xml
内容为/etc/freeswitch/freeswitch.xml
... <extension name="hold_music"> <condition field="destination_number" expression="^moh$"> <action application="answer"/> <action application="playback" data="$${hold_music}"/> </condition> </extension> ... <X-PRE-PROCESS cmd="set" data="hold_music=local_stream://default"/> ... FUTURE: ADD VOICEMAIL
启动 Freeswitch 并配置为在启动时启动
rc-service freeswitch start rc-update add freeswitch
安装 WiFi Web 代理容器
创建和配置容器
lxc-create -n wifi -f /etc/lxc/default.conf -t alpine
创建启动脚本
ln -s lxc /etc/init.d/lxc.wifi
编辑容器的配置文件,位于 /var/lib/lxc/wifi/config,以反映 wifi 容器的网络
内容为/var/lib/lxc/wifi/config
启动容器
/etc/iniit.d/lxc.wifi
配置容器自动启动
rc-update add lxc.wifi
进入 wifi 容器
lxc-console -n wifi
以 root 身份登录
删除过时的 /etc/network/interfaces
rm /etc/network/interfaces
创建并配置新的 /etc/network/interfaces,如下所示
内容为/etc/network/interfaces
启动网络
rc-service networking start
配置远程管理
apk update setup-sshd -c openssh sed -i "s/.PasswordAuthentication yes/PasswordAuthentication no/" /etc/ssh/sshd_config sed -i "s/.UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
启动 ssh
rc-service sshd start
为容器配置密码
passwd
设置 acf 以进行 Web 管理
setup-acf
设置防火墙
apk add acf-awall

安装和配置递归 DNS 服务
安装 unbound 软件包
apk add unbound
使用您喜欢的编辑器配置 /etc/unbound/unbound.conf
内容为/etc/unbound/unobund.conf
安装和配置代理服务
安装必要的软件包
apk add squid squark lighttpd
使用您首选的编辑器配置 /etc/squid/squid.conf
内容为/etc/squid/squid.conf
#Squid config # This port listens for client requests http_port 172.17.48.1:8080 transparent http_port 127.0.0.1:8081 visible_hostname wifi.local cache_mem 8 MB # If you don't have an HD installed comment the "cache_dir" line below cache_dir aufs /var/cache/squid 900 16 256 # Even though we only use one proxy, this line is recommended # More info: http://www.squid-cache.org/Versions/v2/2.7/cfgman/hierarchy_stoplist.html hierarchy_stoplist cgi-bin ? # Keep 7 days of access logs logfile_rotate 7 logformat squark %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt %rG access_log /var/log/squid/access.log squark cache_store_log none pid_filename /var/run/squid.pid # Make sure client IP is passed to Squark log_uses_indirect_client on acl_uses_indirect_client on # Debugging Squid, see http://wiki.squid-cache.org/KnowledgeBase/DebugSections # for more info # Keep 7 days of cache log debug_options rotate=7 # Web auditors want to see the full uri, even with the query terms strip_query_terms off refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern . 0 20% 4320 coredump_dir /var/cache/squid dns_nameservers 172.17.48.1 # # Authentication # # Squark external acl #external_acl_type squark_snmp_auth_D children-max=1 ttl=4 grace=1 negative_ttl=0 concurrency=128 %SRC /usr/bin/squark-auth-snmp -c public -R <SWITCH_IP> -i <D_VLAN_IF> -v <D_VLAN_ID> -f "%N-%i=%I" -T /etc/squark/topology.conf # # Access Control Lists (ACL's) # # Standard ACL settings acl QUERY urlpath_regex cgi-bin \? asp aspx jsp acl to_localhost dst 172.17.48.1 acl SSL_ports port 443 563 8004 9000 acl Safe_ports port 21 70 80 81 210 280 443 563 499 591 777 1024 1022 1025-65535 acl purge method PURGE acl CONNECT method CONNECT #acl SquarkAuth external squark_auth #acl SquarkSnmpAuthD external squark_snmp_auth_D # Squark filter url_rewrite_program /usr/bin/squark-filter url_rewrite_children 1 concurrency=128 # Require authentication acl userlist src all # Definition of zones acl Zone_D src 172.17.48.0/24 # # Access restrictions # cache deny QUERY # Only allow cachemgr access from localhost http_access allow manager localhost http_access deny manager # Only allow purge requests from localhost http_access allow purge localhost http_access deny purge # Deny requests to unknown ports http_access deny !Safe_ports # Deny CONNECT to other than SSL ports http_access deny CONNECT !SSL_ports # Allow hosts in Zone_D to access the entire Internet http_access allow Zone_D # Denying all access not explictly allowed http_access deny all ##Squark URL rewriter #Prevent squark from filtering itself url_rewrite_access deny manager url_rewrite_access deny to_localhost #Finally, permit access url_rewrite_access allow Zone_D http_reply_access allow all icp_access allow all
配置 lighttpd
内容为/etc/lighttpd/lighttpd.conf
var.basedir = "/var/www/localhost" var.logdir = "/var/log/lighttpd" var.statedir = "/var/lib/lighttpd" server.modules = ( "mod_access", "mod_accesslog", "mod_extforward" ) include "mime-types.conf" include "mod_cgi.conf" server.username = "lighttpd" server.groupname = "lighttpd" server.document-root = var.basedir + "/squark" server.pid-file = "/var/run/lighttpd.pid" server.errorlog = var.logdir + "/error.log" server.indexfiles = ("index.php", "index.html", "index.htm", "default.htm") server.follow-symlink = "enable" server.port = 81 server.bind = "172.17.48.1" static-file.exclude-extensions = (".php", ".pl", ".cgi", ".fcgi") accesslog.filename = var.logdir + "/access.log" url.access-deny = ("~", ".inc") extforward.forwarder = ("172.17.48.1" => "trust")
内容为/etc/lighttpd/mod_cgi.conf
############################################################################### # mod_cgi.conf # include'd by lighttpd.conf. # $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_cgi.conf,v 1.1 2005/08/27 12:36:13 ka0ttic Exp $ ############################################################################### # # see cgi.txt for more information on using mod_cgi # server.modules += ("mod_cgi") # NOTE: this requires mod_alias alias.url = ( "/cgi-bin/" => var.basedir + "/cgi-bin/" ) # # Note that you'll also want to enable the # cgi-bin alias via mod_alias (above). # $HTTP["url"] =~ "^/cgi-bin/" { # disable directory listings dir-listing.activate = "disable" # only allow cgi's in this directory cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "/usr/bin/haserl" ) } # vim: set ft=conf foldmethod=marker et :
将 Squark 网页链接到 Web 服务器主目录
ln -s /usr/share/squark/www/ /var/www/localhost/squark
将“squid”和“lighttpd”用户设为 squark 组的成员
addgroup squid squark addgroup lighttpd squark
启动 lighttpd 并配置 Web 服务在启动时启动
rc-service lighttpd start rc-update add lighttpd
启动 Squid 并配置它在启动时启动
rc-service squid start rc-update add squid