Mac系统的Anyconnect Predeploy安装包中集成了VPN、Web Security、Diagnostics and Reporting Tool、AMP Enabler、Posture、ISE Posture、Network Visibility、Umbrella Roaming Security组件,在正常的安装过程中,这些组件都是默认勾选安装的。

虽然安装过程很简单,但是难免有傻X用户看都不看直接下一步,所以我决定优化一下客户端。


最开始的思路是先从官方找,除了Predeploy版本外,官方还提供了Web deploy版本,这两个版本的区别在于Web deploy用于上传到ASA内部,用户从web端访问VPN的时候自动部署anyconnect软件;Pre Deploy是用于预先部署的单独安装包。

官方的anyconnect手册中写了如何通过ASDM定制安装包,但是经过测试ASDM仅支持windows版的定制,手册也没有提供macOS版的相关参数。
不过在手册的#Disable the Customer Experience Feedback Module章节发现了一段描述可以把dmg文件从只读转换为可读写。

Convert the dmg package from read-only to read-write using Disk Utility or hdiutil. For example:

hdiutil convert anyconnect-macosx-i386-ver-k9.dmg -format UDRW -o anyconnect-macosx-i386-ver-k9-rw.dmg

那么新的思路就是修改dmg文件包的内容,再重新打包。
首先是打开anyconnect-macos-4.7.01076-predeploy-k9.dmg,把Anyconnect.pkg复制出来。
使用pkgutil工具解压,目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ pkgutil --expand AnyConnect.pkg anyconnect

$ tree -L 1 anyconnect
anyconnect
├── Distribution
├── Resources
├── dart_module.pkg
├── fireamp_module.pkg
├── iseposture_module.pkg
├── nvm_module.pkg
├── posture_module.pkg
├── umbrella_module.pkg
├── vpn_module.pkg
└── websecurity_module.pkg

Distribution是安装过程中的配置文件
Resources是安装过程中的字体、license服务协议、背景图片等资源
其他的pkg就是各个组件了。

优化的办法就删掉其他pkg,只保留vpn_module.pkg。然后在修改Distribution,注释或者删掉其他组件的调用:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<installer-gui-script minSpecVersion="1">
<title>AnyConnect Secure Mobility Client</title>
<background file="pkg_background.png" scaling="proportional" alignment="bottomleft"/>
<license file="License.rtf"/>
<options customize="always" rootVolumeOnly="true" hostArchitectures="i386"/>
<choices-outline>
<line choice="choice_vpn"/>
<!-- <line choice="choice_websecurity"/>
<line choice="choice_fireamp"/>
<line choice="choice_dart"/>
<line choice="choice_posture"/>
<line choice="choice_iseposture"/>
<line choice="choice_nvm"/>
<line choice="choice_umbrella"/> -->
</choices-outline>
<choice id="choice_vpn" start_enabled="enable_module()" enabled="choice_vpn_enabled()" start_selected="check_upgrade()" selected="choice_vpn_selected()" title="VPN" description="Installs the module that enables VPN capabilities.">
<pkg-ref id="com.cisco.pkg.anyconnect.vpn"/>
</choice>
<!-- <choice id="choice_websecurity" start_selected="check_upgrade()" start_enabled="enable_module()" title="Web Security" description="Installs the WebSecurity module that enables cloud scanning of web content to protect against malware and enforce acceptable use policies via the ScanSafe cloud proxies.">
<pkg-ref id="com.cisco.pkg.anyconnect.websecurity_v2"/>
</choice>
<choice id="choice_dart" start_selected="check_upgrade()" start_enabled="enable_module()" title="Diagnostics and Reporting Tool" description="Installs the diagnostics module that collects AnyConnect Secure Mobility Client troubleshooting information.">
<pkg-ref id="com.cisco.pkg.anyconnect.dart"/>
</choice>
<choice id="choice_fireamp" start_selected="check_upgrade()" start_enabled="enable_module()" title="AMP Enabler" description="Installs the AMP Enabler module that downloads and deploys AMP for Endpoints, as configured by the administrator.">
<pkg-ref id="com.cisco.pkg.anyconnect.fireamp"/>
</choice>
<choice id="choice_posture" start_selected="check_upgrade()" start_enabled="enable_module()" title="Posture" description="Installs the module that provides the AnyConnect Secure Mobility Client with the ability to identify the operating system, antivirus, antispyware, and firewall software installed on the host prior to creating a remote access connection to the secure gateway.">
<pkg-ref id="com.cisco.pkg.anyconnect.posture"/>
</choice>
<choice id="choice_iseposture" start_selected="check_upgrade()" start_enabled="enable_module()" title="ISE Posture" description="Installs the module that provides the AnyConnect Secure Mobility Client with the functionality needed to authenticate to wired or wireless networks controlled by the Identity Services Engine, including examination and any needed remediation of the connecting host environment.">
<pkg-ref id="com.cisco.pkg.anyconnect.iseposture"/>
</choice>
<choice id="choice_nvm" start_selected="check_upgrade()" start_enabled="enable_module()" title="Network Visibility" description="Installs the Network Visibility Module which collects application telemetry data.">
<pkg-ref id="com.cisco.pkg.anyconnect.nvm_v2"/>
</choice>
<choice id="choice_umbrella" start_selected="check_upgrade()" start_enabled="enable_module()" title="Umbrella Roaming Security" description="Installs the module that enables Umbrella Roaming Security.">
<pkg-ref id="com.cisco.pkg.anyconnect.umbrella"/>
</choice> -->
<pkg-ref id="com.cisco.pkg.anyconnect.vpn" version="4.7.01076" installKBytes="22150">#vpn_module.pkg</pkg-ref>
<!-- <pkg-ref id="com.cisco.pkg.anyconnect.dart" version="4.7.01076" installKBytes="4608">#dart_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.websecurity_v2" version="4.7.01076" installKBytes="3052">#websecurity_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.fireamp" version="4.7.01076" installKBytes="786">#fireamp_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.posture" version="4.7.01076" installKBytes="51264">#posture_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.iseposture" version="4.7.01076" installKBytes="3010">#iseposture_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.nvm_v2" version="4.7.01076" installKBytes="1485">#nvm_module.pkg</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.umbrella" version="4.7.01076" installKBytes="3645">#umbrella_module.pkg</pkg-ref> -->
<installation-check script="InstallationCheck()"/>
<volume-check script="VolumeCheck()"/>
<script>

var gUpgradeModules = [];

function check_upgrade()
{
var modulePkgInfo = my.choice.packages[0];
var moduleReceipt = my.target.receiptForIdentifier(modulePkgInfo.identifier);

if (moduleReceipt)
{
var comparison = system.compareVersions(moduleReceipt.version, modulePkgInfo.version);

if (comparison == 0)
{
system.log("Found an existing installed version: " + my.choice.title);
return false;
}
}

gUpgradeModules.push(my.choice.id);
return true;
}

function enable_module()
{
var moduleID = my.choice.id;
return (gUpgradeModules.indexOf(moduleID) &gt; -1);
}

function InstallationCheck()
{
if(!(system.compareVersions(system.version.ProductVersion, '10.9') &gt;= 0))
{
my.result.title = 'Cisco AnyConnect Secure Mobility Client';
my.result.message = 'This software requires Mac OS X version 10.9 or later.';
my.result.type = 'Fatal';
return false;
}

return true;
}

function VolumeCheck()
{
// version of VPN being installed has to be higher than the version already installed

var vpnReceipt = my.target.receiptForIdentifier("com.cisco.pkg.anyconnect.vpn");
var vpnPackage = choices.choice_vpn.packages[0];

// if the receipt is not there assume no VPN installed or pre-3.1.1 version so it is OK to install
if (vpnReceipt)
{
// there is a 3.1.1+ version of VPN already installed
// check to see if version in this package is newer
var comparison = system.compareVersions(vpnReceipt.version, vpnPackage.version);

if (comparison &gt; 0)
{
// installed version is newer
my.result.message = 'Newer version ' + vpnReceipt.version + ' of the Cisco AnyConnect Secure Mobility Client is already installed.';
my.result.type = 'Fatal';
return false;
}
}

return true;
}

function choice_vpn_enabled()
{
if (!enable_module())
{
return false;
}

return (!choices.choice_websecurity.selected &amp;&amp; !choices.choice_posture.selected &amp;&amp; !choices.choice_iseposture.selected &amp;&amp; !choices.choice_fireamp.selected &amp;&amp; !choices.choice_nvm.selected &amp;&amp; !choices.choice_umbrella.selected);
}

function choice_vpn_selected()
{
if (!enable_module())
{
return false;
}

var tSelected;

tSelected=((choices.choice_websecurity.selected || choices.choice_posture.selected || choices.choice_iseposture.selected || choices.choice_fireamp.selected || choices.choice_nvm.selected || choices.choice_umbrella.selected) || (!choices.choice_websecurity.selected &amp;&amp; !choices.choice_posture.selected &amp;&amp; !choices.choice_iseposture.selected &amp;&amp; !choices.choice_fireamp.selected &amp;&amp; !choices.choice_nvm.selected &amp;&amp; !choices.choice_umbrella.selected));

if (choice_vpn_enabled()==false)
{
return tSelected;
}

return (tSelected &amp;&amp; my.choice.selected);
}
</script>
<pkg-ref id="com.cisco.pkg.anyconnect.vpn">
<bundle-version>
<bundle CFBundleShortVersionString="4.7.01076" CFBundleVersion="4.7.01076" id="com.cisco.Cisco-AnyConnect-Secure-Mobility-Client" path="Applications/Cisco/Cisco AnyConnect Secure Mobility Client.app"/>
<bundle CFBundleVersion="4.7.01076" id="com.cisco.vpndownloader" path="opt/cisco/anyconnect/bin/vpndownloader.app"/>
<bundle CFBundleShortVersionString="4.5.03023" CFBundleVersion="4.5.03023" id="com.cisco.Cisco-AnyConnect-Secure-Mobility-Client-Notification" path="opt/cisco/anyconnect/bin/Cisco AnyConnect Secure Mobility Client Notification.app"/>
<bundle CFBundleShortVersionString="4.7.01076" CFBundleVersion="4.7.01076" id="com.cisco.uninstaller" path="Applications/Cisco/Uninstall AnyConnect.app"/>
</bundle-version>
</pkg-ref>
<!-- <pkg-ref id="com.cisco.pkg.anyconnect.websecurity_v2">
<bundle-version/>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.fireamp">
<bundle-version/>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.dart">
<bundle-version>
<bundle CFBundleShortVersionString="4.7.01076" id="com.cisco.pkg.anyconnect.dart" path="Applications/Cisco/Cisco AnyConnect DART.app"/>
<bundle CFBundleShortVersionString="4.7.01076" CFBundleVersion="4.7.01076" id="com.cisco.dartuninstaller" path="Applications/Cisco/Uninstall AnyConnect DART.app"/>
</bundle-version>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.posture">
<bundle-version/>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.iseposture">
<bundle-version/>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.nvm_v2">
<bundle-version/>
</pkg-ref>
<pkg-ref id="com.cisco.pkg.anyconnect.umbrella">
<bundle-version>
<bundle CFBundleVersion="1.5.5" id="com.opendns.OpenDNS-Diagnostic" path="opt/cisco/anyconnect/bin/UmbrellaDiagnostic.app"/>
</bundle-version>
</pkg-ref> -->
</installer-gui-script>

简单看了下里面的判断逻辑,还需要吧<choice id="choice_vpn" start_enabled="enable_module()"修改为<choice id="choice_vpn" start_enabled="1"即可。

使用pkgutil重新打包

1
$pkgutil  --flatten anyconnect Anyconnect-New.pkg

重新挂载之前改为可读写的dmg,然后替换新的pkg文件。移除挂载后,再用macOS磁盘工具重新调整dmg的大小,调整后改为只读:

在 Mac 上使用“磁盘工具”调整磁盘映像大小

1
$hdiutil convert anyconnect-macos-4.7.01076-predeploy-k9-rw.dmg -format UDRO -o anyconnect-macos-4.7.01076-VPN.dmg

参考资料:
Cisco AnyConnect Secure Mobility Client Administrator Guide, Release 4.7