Tommy 碎碎念
https://blog.teatime.com.tw/
Tommy Wu's blog
tommy
2024-03-19T15:07:02Z
-
修正 Cisco AnyConnect 在 Windows 無法正常使用問題
https://blog.teatime.com.tw/1/post/481
<p>在安裝 <a href="http://www.infradead.org/ocserv/" target="_blank">OpenConnect VPN server</a> 之後, 有使用 AnyConnect 的 client 試過, 發現一直無法正常連線. (應該說可以連線, 但是在啟用網卡沒多久後會跳到修護網卡然後就說無法正常連線)</p><p>查了一下 Google, 似乎都只有提到下面兩種作法:</p><ul><li><a href="http://www.robertschultz.org/cisco-anyconnect-vpn-with-windows-8-fixed/" target="_blank">修改 vpnva 的 DisplayName 值</a>. </li><li><a href="https://www.reddit.com/r/Windows10/comments/34duvd/cisco_anyconnect_still_broken_on_10074/" target="_blank">停用 ipv6, 改 ipv4 為 dhcp</a>.</li></ul><p>不過... 我試了都沒用.... 原本打算放棄, 後來發現, 有些機器上又可以正常使用, 比對一下, 似乎有裝 OpenConnect Client 或 OpenVPN 的都無法正常使用. 所以懷疑可能是與 TAP 網卡有衝突... 就試著把 TAP 網卡停用, 果然就可以正常連線了.</p><p>不過由於每次要用 AnyConnect 就要停用 TAP 網卡, 要用 OpenConnect 或 OpenVPN 就要去啟用 TAP 網卡, 用滑鼠做比較麻煩, 就試著用 netsh 指令來做. 不過... 這需要使用到網卡名稱, 而預設安裝後, 在英文下可能是 "Local Area Network X", 而中文下可能是 "區域網路 X", 不太好下指令... 所以就先到控制台把這個網卡名改成比較容易使用的 TAP0901, 然後用下面的指令停用:</p><pre class="winbatch"><div class="insertcode">netsh interface set interface name=TAP0901 admin=<span class="kw2">disable</span></div></pre><p>要啟用就用:</p><pre class="winbatch"><div class="insertcode">netsh interface set interface name=TAP0901 admin=<span class="kw2">enable</span></div></pre><p>這樣只要點一下就能做到啟用與停用的動作.</p>
Software
VPN
2016-07-16T11:32:15Z
tommy
-
架設 OpenConnect VPN server
https://blog.teatime.com.tw/1/post/480
<p>在 Debian 中安裝 <a href="http://www.infradead.org/ocserv/" target="_blank">OpenConnect VPN server</a> 其實很簡單, 應該只要一行 apt-get install ocserv 指令就可以了.</p><p>安裝後只要去修改 /etc/ocserv/ocserv.conf 設定, 改變 tcp-port, udp-port, server-cert, server-key 就可以:</p><pre class="ini"><div class="insertcode"># TCP and UDP port number<br /># When systemd is running as init, this needs to be adjusted in<br /># the corresponding unit file as well.<br /><span class="re1">tcp-port</span> <span class="sy0">=</span><span class="re2"> 8443</span><br /><span class="re1">udp-port</span> <span class="sy0">=</span><span class="re2"> 8443</span><br /> <br /># The key and the certificates of the server<br /># The key may be a file, or any URL supported by GnuTLS <span class="br0">(</span>e.g.,<br /># tpmkey:uuid<span class="sy0">=</span><span class="re2">xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx</span><span class="co0">;storage=user</span><br /># or pkcs11:object<span class="sy0">=</span><span class="re2">my-vpn-key</span><span class="co0">;object-type=private)</span><br />#<br /># The server-cert file may contain a single certificate, or<br /># a sorted certificate chain.<br />#<br /># There may be multiple server-cert and server-key directives,<br /># but each key should correspond to the preceding certificate.<br /><span class="re1">server-cert</span> <span class="sy0">=</span><span class="re2"> /etc/letsencrypt.sh/certs/default/fullchain.pem</span><br /><span class="re1">server-key</span> <span class="sy0">=</span><span class="re2"> /etc/letsencrypt.sh/certs/default/privkey.pem</span></div></pre><p>預設的 port 是 443, 不過... 通常 443 都給 https 用了, 所以就找別的 port 來用... 如果你的系統是用 systemd (如果不是很久沒更新的版本, 應該都是了), 還用去改 /lib/systemd/system/ocserv.socket 裡頭的設定才可以. </p><p>憑證的部份可以用 <a href="https://letsencrypt.org/" target="_blank">Let's encrypt</a> 的憑證就可以. </p><p>由於 OpenConnect 與 Cisco AnyConnect 基本上是相容的, 只要加上下面的設定就可以:</p><pre class="ini"><div class="insertcode"># This option must be set to true to support legacy CISCO clients.<br /># A side effect of this option is that it will no longer be required<br /># for clients to present their certificate on every connection.<br /># That is they may resume a cookie without presenting a certificate<br /># <span class="br0">(</span>when certificate authentication is used<span class="br0">)</span>.<br /><span class="re1">cisco-client-compat</span> <span class="sy0">=</span><span class="re2"> true</span><br /> <br /># Client profile xml. A sample file exists in doc/profile.xml.<br /># It is required by some of the CISCO clients.<br /># This file must be accessible from inside the worker's chroot.<br /># Note that enabling this option is not recommended as it will allow<br /># the worker processes to open arbitrary files <span class="br0">(</span>when isolate-workers is<br /># set to true<span class="br0">)</span>.<br /><span class="re1">user-profile</span> <span class="sy0">=</span><span class="re2"> /etc/ocserv/profile.xml</span></div></pre><p>user-profile 並非一定要 (有設定這個時, 在 AnyConnect Client 上頭會用名稱取代 ip adreess 或 hostname), profile.xml 的內容如下:</p><pre class="xml"><div class="insertcode"><span class="sc3"><span class="re1"><?xml</span> <span class="re0">version</span>=<span class="st0">"1.0"</span> <span class="re0">encoding</span>=<span class="st0">"UTF-8"</span><span class="re2">?></span></span><br /><span class="sc3"><span class="re1"><AnyConnectProfile</span> <span class="re0">xmlns</span>=<span class="st0">"http://schemas.xmlsoap.org/encoding/"</span> <span class="re0">xmlns:xsi</span>=<span class="st0">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="re0">xsi:schemaLocation</span>=<span class="st0">"http://schemas.xmlsoap.org/encoding/ AnyConnectProfile.xsd"</span><span class="re2">></span></span><br /> <br /> <span class="sc3"><span class="re1"><ClientInitialization<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><UseStartBeforeLogon</span> <span class="re0">UserControllable</span>=<span class="st0">"false"</span><span class="re2">></span></span>false<span class="sc3"><span class="re1"></UseStartBeforeLogon<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><StrictCertificateTrust<span class="re2">></span></span></span>false<span class="sc3"><span class="re1"></StrictCertificateTrust<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><RestrictPreferenceCaching<span class="re2">></span></span></span>false<span class="sc3"><span class="re1"></RestrictPreferenceCaching<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><RestrictTunnelProtocols<span class="re2">></span></span></span>IPSec<span class="sc3"><span class="re1"></RestrictTunnelProtocols<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><BypassDownloader<span class="re2">></span></span></span>true<span class="sc3"><span class="re1"></BypassDownloader<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><WindowsVPNEstablishment<span class="re2">></span></span></span>AllowRemoteUsers<span class="sc3"><span class="re1"></WindowsVPNEstablishment<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><CertEnrollmentPin<span class="re2">></span></span></span>pinAllowed<span class="sc3"><span class="re1"></CertEnrollmentPin<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><CertificateMatch<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><KeyUsage<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><MatchKey<span class="re2">></span></span></span>Digital_Signature<span class="sc3"><span class="re1"></MatchKey<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></KeyUsage<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><ExtendedKeyUsage<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><ExtendedMatchKey<span class="re2">></span></span></span>ClientAuth<span class="sc3"><span class="re1"></ExtendedMatchKey<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></ExtendedKeyUsage<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></CertificateMatch<span class="re2">></span></span></span><br /> <br /> <span class="sc3"><span class="re1"><BackupServerList<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><HostAddress<span class="re2">></span></span></span>vpn.teatime.com.tw<span class="sc3"><span class="re1"></HostAddress<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></BackupServerList<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></ClientInitialization<span class="re2">></span></span></span><br /> <br /> <span class="sc3"><span class="re1"><ServerList<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><HostEntry<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><HostName<span class="re2">></span></span></span>TeaTime VPN Server<span class="sc3"><span class="re1"></HostName<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"><HostAddress<span class="re2">></span></span></span>vpn.teatime.com.tw<span class="sc3"><span class="re1"></HostAddress<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></HostEntry<span class="re2">></span></span></span><br /> <span class="sc3"><span class="re1"></ServerList<span class="re2">></span></span></span><br /><span class="sc3"><span class="re1"></AnyConnectProfile<span class="re2">></span></span></span></div></pre><p>就是改 HostName 與 HostAddress 就可以.</p><p>至於 client 端的程式, 可以用 OpenConnect 或 Cisco AnyConnect 的都可以 (各平台幾乎都有), 不過建議用 OpenConnect 會比較好用... Cisco 的 AnyConnect 似乎只會保留最後一次連線的設定 (是我不會用嗎?), 如果要連不同的 server, 不能簡單的選擇 profile 來用.</p><p>最後, 通常是直接用 pam 來管理可以連線的使用者 (可以搭配 pam_listfile.so 來控管), 如果要搭配 AD 帳號來用的話, <a href="http://www.infradead.org/ocserv/recipes-ocserv-kerberos.html" target="_blank">官網有篇文章</a>有提到, 不過... 看起來似乎很麻煩... 我會選擇用 pam_script.so 來處理.</p><p>/etc/pam.d/ocserv:</p><pre class="ini"><div class="insertcode">#<br /># /etc/pam.d/ocserv - specify the PAM behaviour of ocserv<br />#<br /> <br />#auth required pam_listfile.so item<span class="sy0">=</span><span class="re2">user sense=allow file=/etc/users/vpn onerr=fail</span><br /> <br /># Standard Un*x authentication.<br />auth required pam_script.so<br /> <br /># Disallow non-root logins when /etc/nologin exists.<br />account required pam_nologin.so<br /> <br /># Uncomment and edit /etc/security/access.conf if you need to set complex<br /># access limits.<br /># account required pam_access.so<br /> <br /># Standard Un*x authorization.<br />account required pam_script.so<br /> <br /># SELinux needs to be the first session rule. This ensures that any<br /># lingering context has been cleared. Without out this it is possible<br /># that a module could execute code in the wrong domain.<br />session <span class="re0"><span class="br0">[</span>success<span class="sy0">=</span><span class="re2">ok ignore=ignore module_unknown=ignore default=bad<span class="br0">]</span></span> pam_selinux.so close</span><br /> <br /># Standard Un*x session setup and teardown.<br />session required pam_script.so<br /> <br /># Set up user limits from /etc/security/limits.conf.<br />session required pam_limits.so<br /> <br /># SELinux needs to intervene at login time to ensure that the process starts<br /># in the proper default security context. Only sessions which are intended<br /># to run in the user's context should be run after this.<br />session <span class="re0"><span class="br0">[</span>success<span class="sy0">=</span><span class="re2">ok ignore=ignore module_unknown=ignore default=bad<span class="br0">]</span></span> pam_selinux.so open</span><br /> <br />password required pam_script.so</div></pre><p>在 Debian 底下, pam_script.so 的指令放 /usr/share/libpam-script 目錄下. 需要有 pam_script_acct, pam_script_auth, pam_script_passwd, pam_script_ses_open, pam_script_ses_close 這幾個檔案 (用不到也要用, 不然 pam 會失敗).</p><p>我們只會用到 pam_script_auth 這一個, 其他的, 可以直接用:</p><pre class="bash"><div class="insertcode"><span class="co0">#!/bin/sh</span><br /> <br /><span class="kw3">exit</span> <span class="nu0">0</span></div></pre><p>表示成功就可以. 而 pam_script_auth 這一個, 我們可以使用 PHP 的 ldap 去做 AD bind 的動作並查詢是否屬於可以使用 VPN 的 group, 就可以透過 AD 來控管可連線的使用者了.</p><p>例如:</p><pre class="php"><div class="insertcode">#!/usr/bin/php -Cq<br /><span class="kw2"><?php</span><br /> <br /><span class="re0">$root_path</span> <span class="sy0">=</span> <a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">(</span><span class="re0">$argv</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="kw1">if</span> <span class="br0">(</span><span class="re0">$root_path</span> <span class="sy0">!==</span> <span class="st_h">''</span><span class="br0">)</span><br /> <span class="re0">$root_path</span> <span class="sy0">.=</span> <span class="st_h">'/'</span><span class="sy0">;</span><br /><span class="kw1">require_once</span><span class="br0">(</span><span class="re0">$root_path</span><span class="sy0">.</span><span class="st_h">'config.php'</span><span class="br0">)</span><span class="sy0">;</span><br /> <br /><span class="re0">$aGroup</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span><br /> <br /><span class="kw2">function</span> writelog<span class="br0">(</span><span class="re0">$str</span><span class="br0">)</span><br /><span class="br0">{</span><br /> <span class="kw2">global</span> <span class="re0">$root_path</span><span class="sy0">;</span><br /> <br /> <span class="kw1">echo</span> <span class="re0">$str</span><span class="sy0">.</span><span class="st0">"<span class="es1">\n</span>"</span><span class="sy0">;</span><br /> <span class="re0">$fp</span> <span class="sy0">=</span> <a href="http://www.php.net/fopen"><span class="kw3">fopen</span></a><span class="br0">(</span><span class="re0">$root_path</span><span class="sy0">.</span><span class="st_h">'log/ocserv_auth_'</span><span class="sy0">.</span><a href="http://www.php.net/strftime"><span class="kw3">strftime</span></a><span class="br0">(</span><span class="st_h">'%Y%m%d'</span><span class="br0">)</span><span class="sy0">.</span><span class="st_h">'.log'</span><span class="sy0">,</span> <span class="st_h">'at'</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$fp</span><span class="br0">)</span> <span class="br0">{</span><br /> <a href="http://www.php.net/fputs"><span class="kw3">fputs</span></a><span class="br0">(</span><span class="re0">$fp</span><span class="sy0">,</span> <a href="http://www.php.net/strftime"><span class="kw3">strftime</span></a><span class="br0">(</span><span class="st_h">'%H:%M:%S'</span><span class="br0">)</span><span class="sy0">.</span><span class="st0">" <span class="es4">$str</span><span class="es1">\n</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /> <a href="http://www.php.net/fclose"><span class="kw3">fclose</span></a><span class="br0">(</span><span class="re0">$fp</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /> <span class="kw1">return</span><span class="sy0">;</span><br /><span class="br0">}</span><br /> <br /><span class="kw2">function</span> getAllGroupForGroup<span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$group_dn</span><span class="br0">)</span><br /><span class="br0">{</span><br /> <span class="kw2">global</span> <span class="re0">$base_dn</span><span class="sy0">;</span><br /> <span class="kw2">global</span> <span class="re0">$aGroup</span><span class="sy0">;</span><br /> <br /> <span class="re0">$sr</span> <span class="sy0">=</span> <a href="http://www.php.net/ldap_search"><span class="kw3">ldap_search</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$base_dn</span><span class="sy0">,</span> <span class="st_h">'(distinguishedName='</span><span class="sy0">.</span><span class="re0">$group_dn</span><span class="sy0">.</span><span class="st_h">')'</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="re0">$data</span> <span class="sy0">=</span> <a href="http://www.php.net/ldap_get_entries"><span class="kw3">ldap_get_entries</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$sr</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$data</span><span class="br0">[</span><span class="st_h">'count'</span><span class="br0">]</span> <span class="sy0"><=</span> <span class="nu0">0</span><span class="br0">)</span><br /> <span class="kw1">return</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">(</span><span class="st_h">'memberof'</span><span class="sy0">,</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="kw1">return</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="re0">$cnt</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'memberof'</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'count'</span><span class="br0">]</span><span class="sy0">;</span><br /> <span class="kw1">for</span> <span class="br0">(</span><span class="re0">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span> <span class="sy0"><</span> <span class="re0">$cnt</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">++</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$group</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'memberof'</span><span class="br0">]</span><span class="br0">[</span><span class="re0">$i</span><span class="br0">]</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">(</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$aGroup</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$aGroup</span><span class="br0">[</span><span class="br0">]</span> <span class="sy0">=</span> <span class="re0">$group</span><span class="sy0">;</span><br /> getAllGroupForGroup<span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$group</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /> <span class="br0">}</span><br /> <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br /><span class="br0">}</span><br /> <br /><span class="kw2">function</span> getAllGroupForUser<span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$empid</span><span class="br0">)</span><br /><span class="br0">{</span><br /> <span class="kw2">global</span> <span class="re0">$base_dn</span><span class="sy0">;</span><br /> <span class="kw2">global</span> <span class="re0">$sec_key</span><span class="sy0">;</span><br /> <span class="kw2">global</span> <span class="re0">$aGroup</span><span class="sy0">;</span><br /> <br /> <span class="re0">$aGroup</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="re0">$sr</span> <span class="sy0">=</span> <a href="http://www.php.net/ldap_search"><span class="kw3">ldap_search</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$base_dn</span><span class="sy0">,</span> <span class="re0">$sec_key</span><span class="sy0">.</span><span class="st_h">'='</span><span class="sy0">.</span><span class="re0">$empid</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="re0">$data</span> <span class="sy0">=</span> <a href="http://www.php.net/ldap_get_entries"><span class="kw3">ldap_get_entries</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$sr</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="re0">$data</span><span class="br0">[</span><span class="st_h">'count'</span><span class="br0">]</span> <span class="sy0"><=</span> <span class="nu0">0</span><span class="br0">)</span><br /> <span class="kw1">return</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><a href="http://www.php.net/array_key_exists"><span class="kw3">array_key_exists</span></a><span class="br0">(</span><span class="st_h">'memberof'</span><span class="sy0">,</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">)</span><span class="br0">)</span><br /> <span class="kw1">return</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="re0">$cnt</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'memberof'</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'count'</span><span class="br0">]</span><span class="sy0">;</span><br /> <span class="kw1">for</span> <span class="br0">(</span><span class="re0">$i</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="re0">$i</span> <span class="sy0"><</span> <span class="re0">$cnt</span><span class="sy0">;</span> <span class="re0">$i</span><span class="sy0">++</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$group</span> <span class="sy0">=</span> <span class="re0">$data</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="br0">[</span><span class="st_h">'memberof'</span><span class="br0">]</span><span class="br0">[</span><span class="re0">$i</span><span class="br0">]</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><a href="http://www.php.net/in_array"><span class="kw3">in_array</span></a><span class="br0">(</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$aGroup</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$aGroup</span><span class="br0">[</span><span class="br0">]</span> <span class="sy0">=</span> <span class="re0">$group</span><span class="sy0">;</span><br /> getAllGroupForGroup<span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$group</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /> <span class="br0">}</span><br /> <span class="kw1">return</span> <span class="kw4">true</span><span class="sy0">;</span><br /><span class="br0">}</span><br /> <br /><span class="coMULTI">/*<br /># PAM_SERVICE - the application that's invoking the PAM stack<br /># PAM_TYPE - the module-type (e.g. auth,account,session,password)<br /># PAM_USER - the user being authenticated into<br /># PAM_RUSER - the remote user, the user invoking the application<br /># PAM_RHOST - remote host<br /># PAM_TTY - the controlling tty<br /># PAM_AUTHTOK - password in readable text<br />*/</span><br /><span class="re0">$emp_id</span> <span class="sy0">=</span> <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">(</span><span class="st_h">'PAM_USER'</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="re0">$ldap_user</span> <span class="sy0">=</span> <span class="re0">$emp_id</span><span class="sy0">.</span><span class="st_h">'@'</span><span class="sy0">.</span><span class="re0">$mydomain</span><span class="sy0">;</span><br /><span class="re0">$ldap_pass</span> <span class="sy0">=</span> <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">(</span><span class="st_h">'PAM_AUTHTOK'</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="re0">$rhost</span> <span class="sy0">=</span> <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">(</span><span class="st_h">'PAM_RHOST'</span><span class="br0">)</span><span class="sy0">;</span><br /> <br />writelog<span class="br0">(</span><span class="st0">"user=<span class="es4">$emp_id</span>, rhost=<span class="es4">$rhost</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="co1">// Attempting fix from http://www.php.net/manual/en/ref.ldap.php#77553</span><br /><a href="http://www.php.net/putenv"><span class="kw3">putenv</span></a><span class="br0">(</span><span class="st_h">'LDAPTLS_REQCERT=never'</span><span class="br0">)</span><span class="sy0">;</span><br /> <br /><span class="re0">$ldap</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br /><span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$ldap_servers</span> <span class="kw1">as</span> <span class="re0">$server</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$ldap</span> <span class="sy0">=</span> <span class="sy0">@</span><a href="http://www.php.net/ldap_connect"><span class="kw3">ldap_connect</span></a><span class="br0">(</span><span class="st_h">'ldap://'</span><span class="sy0">.</span><span class="re0">$server</span><span class="br0">)</span><span class="sy0">;</span><br /> <a href="http://www.php.net/ldap_set_option"><span class="kw3">ldap_set_option</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> LDAP_OPT_REFERRALS<span class="sy0">,</span> <span class="nu0">0</span><span class="br0">)</span><span class="sy0">;</span><br /> <a href="http://www.php.net/ldap_set_option"><span class="kw3">ldap_set_option</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> LDAP_OPT_PROTOCOL_VERSION<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><a href="http://www.php.net/strtoupper"><span class="kw3">strtoupper</span></a><span class="br0">(</span><a href="http://www.php.net/substr"><span class="kw3">substr</span></a><span class="br0">(</span><span class="kw4">PHP_OS</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">3</span><span class="br0">)</span><span class="br0">)</span> <span class="sy0">!==</span> <span class="st_h">'WIN'</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$encrypted</span> <span class="sy0">=</span> <a href="http://www.php.net/ldap_start_tls"><span class="kw3">ldap_start_tls</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="re0">$encrypted</span><span class="br0">)</span> <span class="br0">{</span><br /> <a href="http://www.php.net/ldap_close"><span class="kw3">ldap_close</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="re0">$ldap</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="kw1">continue</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /> <span class="br0">}</span><br /> <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">@</span><a href="http://www.php.net/ldap_bind"><span class="kw3">ldap_bind</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$ldap_user</span><span class="sy0">,</span> <span class="re0">$ldap_pass</span><span class="br0">)</span> <span class="sy0">===</span> <span class="kw4">false</span><span class="br0">)</span> <span class="br0">{</span><br /> <a href="http://www.php.net/ldap_close"><span class="kw3">ldap_close</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="br0">)</span><span class="sy0">;</span><br /> <span class="re0">$ldap</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <span class="kw1">continue</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /> <span class="kw1">break</span><span class="sy0">;</span><br /><span class="br0">}</span><br /> <br /><span class="kw1">if</span> <span class="br0">(</span><span class="re0">$ldap</span> <span class="sy0">===</span> <span class="kw4">false</span><span class="br0">)</span> <span class="br0">{</span><br /> writelog<span class="br0">(</span><span class="st0">"bind failed, user=<span class="es4">$emp_id</span>, rhost=<span class="es4">$rhost</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /> <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="br0">}</span><br /> <br />getAllGroupForUser<span class="br0">(</span><span class="re0">$ldap</span><span class="sy0">,</span> <span class="re0">$emp_id</span><span class="br0">)</span><span class="sy0">;</span><br /><a href="http://www.php.net/ldap_close"><span class="kw3">ldap_close</span></a><span class="br0">(</span><span class="re0">$ldap</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="re0">$ldap</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br /> <br /><span class="re0">$in_group</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br /><span class="kw1">foreach</span> <span class="br0">(</span><span class="re0">$aGroup</span> <span class="kw1">as</span> <span class="re0">$group</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="kw1">if</span> <span class="br0">(</span><a href="http://www.php.net/strcasecmp"><span class="kw3">strcasecmp</span></a><span class="br0">(</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$vpn_group</span><span class="br0">)</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">)</span> <span class="br0">{</span><br /> <span class="re0">$in_group</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br /> <span class="kw1">break</span><span class="sy0">;</span><br /> <span class="br0">}</span><br /><span class="br0">}</span><br /> <br /><span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="re0">$in_group</span><span class="br0">)</span> <span class="br0">{</span><br /> writelog<span class="br0">(</span><span class="st0">"failed, not in VPN group, user=<span class="es4">$emp_id</span>, rhost=<span class="es4">$rhost</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /> <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="br0">}</span><br />writelog<span class="br0">(</span><span class="st0">"authenticated, user=<span class="es4">$emp_id</span>, rhost=<span class="es4">$rhost</span>"</span><span class="br0">)</span><span class="sy0">;</span><br /><a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">0</span><span class="br0">)</span><span class="sy0">;</span></div></pre><p>設定的 config.php 要有下面幾個資料:</p><pre class="php"><div class="insertcode"><span class="kw2"><?php</span><br /> <br /><span class="re0">$ldap_servers</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="st_h">'192.168.0.1'</span><span class="sy0">,</span> <span class="st_h">'192.168.0.2'</span><span class="br0">)</span><span class="sy0">;</span><br /><span class="re0">$mydomain</span> <span class="sy0">=</span> <span class="st_h">'domain.teatime.com.tw'</span><span class="sy0">;</span><br /><span class="re0">$base_dn</span> <span class="sy0">=</span> <span class="st_h">'DC=domain,DC=teatime,DC=com,DC=tw'</span><span class="sy0">;</span><br /><span class="re0">$sec_key</span> <span class="sy0">=</span> <span class="st_h">'samaccountname'</span><span class="sy0">;</span><br /><span class="re0">$vpn_group</span> <span class="sy0">=</span> <span class="st_h">'CN=VPN,DC=domain,DC=teatime,DC=com,DC=tw'</span><span class="sy0">;</span></div></pre><p>透過這樣的處理, 我覺得比官網那個方式簡單一些.</p>
Linux
VPN
2016-07-15T10:05:35Z
tommy