Setup IKEv2 On Demand VPN on iOS 8 and IKEv2, IKEv1 Cisco IPSec VPN with Strongswan

First, install Strongswan on Ubuntu.
首先,在Ubuntu上安装Strongswan。
sudo apt-get install strongswan strongswan-plugin-eap-mschapv2 strongswan-plugin-xauth-generic
[info]If you want to compile from source, you need to add this to your configure command:
如果你想从源码编译,请确保你的configure指令包含以下参数:
./configure --prefix=/usr --sysconfdir=/etc --enable-eap-mschapv2 --enable-eap-identity --enable-eap-peap --enable-openssl --enable-md4
https://lists.strongswan.org/pipermail/users/2012-November/003975.html
You can use these command to install Strongswan from source:
你可以用这些命令来从源码安装Strongswan:
apt-get install build-essential libssl-dev libgmp-dev
wget http://download.strongswan.org/strongswan-5.2.0.tar.bz2
tar xjvf strongswan-5.2.0.tar.bz2; cd strongswan-5.2.0
./configure --prefix=/usr --sysconfdir=/etc --enable-eap-mschapv2 --enable-eap-identity --enable-eap-peap --enable-openssl --enable-md4
make & make install
[/info]
apt-get also suggest some packages, some of them are useful if you want to connect your strongswan with Radius or something else.
apt-get会列出一些推荐的包,如果你需要扩展Strongswan的功能比如连接Radius、mysql之类的后端数据库,那你可能会需要安装这些插件。
Suggested packages:
strongswan-tnc-imcvs network-manager-strongswan strongswan-plugin-agent
strongswan-plugin-certexpire strongswan-plugin-coupling
strongswan-plugin-curl strongswan-plugin-dnscert strongswan-plugin-dnskey
strongswan-plugin-duplicheck strongswan-plugin-error-notify
strongswan-plugin-ipseckey strongswan-plugin-ldap strongswan-plugin-led
strongswan-plugin-lookip strongswan-plugin-ntru strongswan-plugin-pkcs11
strongswan-plugin-radattr strongswan-plugin-sql strongswan-plugin-soup
strongswan-plugin-unity strongswan-plugin-whitelist strongswan-tnc-client
strongswan-tnc-server

Now, use
现在使用

ipsec version

to check if ipsec installd successful
命令来检查ipsec的安装是否成功

Then, open /etc/ipsec.secrets. If this file not exists, create a new one.
然后编辑/etc/ipsec.secrets文件。如果不存在就创建一个。
Sudo vim /etc/ipsec.secrets

Write this:
添加如下内容:
: RSA vpnHostKey.pem
: PSK yourpskhere
user1 : EAP "topsecretpassword"
user1 : XAUTH "topsecretpassword"
user2 : XAUTH "evenmoretopsecretpassword"

For security reasons, please change the password in the file, not just use the one I gave.
为了安全起见,请不要使用文中提供的账号密码,使用自定义的账号密码。

By the way, there is a command to reload this file without restart IPSec:
顺便一说,有一个命令可以热加载这个文件:
sudo ipsec rereadsecrets

You can use it to flush the secrets after you modify this file.
在修改了这个文件之后可以直接使用这个命令刷新新的用户密码。

Then modify system config to fit ip forward:
接下来修改系统配置以开启IP包转发:

sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

Then set up iptables to enable forward. If you skip this step or make some mistakes, your VPN may can only connect to the server it self or you may lose SSH connection after you start the iptables.
接下来修改iptables的配置来启用转发。如果你跳过了这一步,你的VPN就只能访问服务器本身;如果你在这一步出错,可能会导致你的SSH链接丢失,然后连不上VPN。
[info]If you have any question, please contact me. wzxjohn#gmail
如果你在设置过程中遇到了困难,欢迎联系我。wzxjohn#gmail[/info]
[info]If you use Debian, you don’t need to use ufw. Just use iptables it self.DO NOT INSTALL ufw!
如果你使用Debian系统,你不需要使用ufw。用直接用iptables即可。不要安装ufw
Just create iptables.up.rules and put “iptables-restore < /etc/iptables.up.rules" in /etc/rc.local. 创建iptables.up.rules文件并把"iptables-restore < /etc/iptables.up.rules" 写入 /etc/rc.local 文件即可。[/info] sudo vim /etc/iptables.up.rules If the file is not exists, create a new one. 编辑/etc/iptables.up.rules文件。如果不存在就创建一个。 https://gist.github.com/wzxjohn/3d1f275b1a36b39475d8 Then put 然后将下面两行 iptables-restore < /etc/iptables.up.rules ufw reload
in /etc/rc.local
写入/etc/rc.local

Now it’s better to restart your VPS now.
现在最好重启一下你的VPS来看看设置是否正确。

If you don’t want to restart, just type
如果你不想重启,可以使用如下命令:
ufw enable
ufw reload

to make sure the iptables rules are working
来确保iptables规则正确加载

Now about ipsec config
接下来是ipsec配置。

This is my config file:
这是我的ipsec配置文件:

I may add some comments later.
之后我可能会添加一些注视。

This config file has 4 part, defined 3 kinds of VPN: IKEv2, IKEv2 with EAP, CiscoIPSec(IKEv1).
这个配置文件包含了4个部分,定义了三种VPN:IKEv2, IKEv2 with EAP, CiscoIPSec(IKEv1)

Save the config file and type ipsec restart in console.
保存配置文件并执行ipsec restart

Then, about the server cert, in the ipsec.config, we defined the file name server.pem.
接下来是关于服务端证书。在ipsec.config文件里,我们定义了证书文件的名字server.pem。

[info]You can also use Wildcard SSL certs, but you should modify the leftid in the ipsec.conf to @*.your.domain
你也可以使用通配符SSL证书,但是你需要修改ipsec.conf中的leftid为@*.your.domain

And the server address must end in your.domain, which means it can be a.your.domain, b.your.domain, c.your.domain etc.
并且服务器域名必须以your.domain结尾,比如a.your.domain, b.your.domain, c.your.domain等等。

So you can use exactly same config file and cert on all of your servers. All you should do is give them different sub domain names.
所以你可以在你的所有服务器上使用完全相同的配置。你只需要给它们分配不同的子域名即可。
[/info]

[warning]The Common Name in the cert must match the leftid and the real server domain name.
证书中所写的Common Name必须与配置中的leftid和真实的服务器域名匹配。

Which means if you want to access your server by a.your.domain, the Common Name in the cert should exactly be a.your.domain or *.your.domain. Any other string is not accept.
也就是说,如果你想用a.your.domain来访问你的服务器,那证书中的Common Name就必须是a.your.domain或者*.your.domain。其余字符都不可以。

And the left id in ipsec.conf should be @a.your.domain or @*.your.domain.
并且ipsec.conf中的leftid必须是@a.your.domain 或者 @*.your.domain

If not, it will cause connection error because of cert don’t match.
如果有任何不满足,都会导致因证书不匹配的连接失败。
[/warning]

[info]I haven’t try about no domain server, according to the documents about config, you may use self-certificate cert and change the leftid in ipsec.conf, and need to install CA cert on your device.
目前没有尝试过纯使用IP的服务端,按照配置文件的写法应该是需要自签名证书和修改leftid,并且需要将自签名CA安装到手机上。

Update 10/10/2014:
Accroding to Justin’s test, if you want to use IP as the server address, you need to follow these three suggestions:
根据Justin的测试,如果你想使用纯IP的服务器,你需要遵守这三条建议:

1.When creating server cert, you need to use:
当创建服务端证书的时候,你需要使用:
--dn "C=CH, O=strongSwan, CN=Server-IP-Address" \
--san Server-IP-Address \

instead of Server Domain name.
而不是服务器的域名

2.About ipsec.conf,the leftid in it should be exactly the server’s ip address, like:
在ipsec.conf文件中,leftid必须是服务器的IP地址,比如:
leftid = 123.456.789.123

3.About the mobileconfig file, the RemoteIdentifier should be exactly the server’s ip address, like:
在配置文件中,远程标识符必须是服务器的IP地址,如:
RemoteIdentifier
123.456.789.123
[/info]

Just rename your domain cert to the name you set and put it in /etc/ipsec.d/certs/, it’s server.pem in this case.
把你给你的域名申请的证书重命名成配置文件中的名称然后放进/etc/ipsec.d/certs/文件夹,这里是server.pem。

For private key, the file name is defined in ipsec.secrets, as vpnHostKey.pem in this case.
关于证书对应的私钥,ipsec.secrets文件中定义了其文件名,这里是vpnHostKey.pem。

Just rename your own private key to this name and put it in /etc/ipsec.d/private/.
把你的域名证书对应的私钥重命名成配置文件中的名称然后放入/etc/ipsec.d/private/。

[info]Here server.pem is what we call ssl.crt(SSLCertificateFile) in setting up Apache SSL site.
这里的server.pem是我们在配置Apache的SSL时通常所说的ssl.crt(SSLCertificateFile)。

The vpnHostKey.pem is what we call ssl.key(SSLCertificateKeyFile) or private key for cert.
vpnHostKey.pe是我们通常所说的ssl.key(SSLCertificateKeyFile)或者叫证书私钥。
[/info]

Then execute ipsec restart than every thing you should do on server side is done.
接下来执行ipsec restart,然后服务端的所有配置就完成了。

Now for mobileconfig file for iOS 8.
然后是给iOS 8使用的配置文件。

This is my mobile config profile:
这是我在使用的配置文件:

Please modify the username, password, server address in this profile and than install it on your device. You can use import function in Apple Configurator or just modify it use any text editor.
在使用前请修改用户名,密码,服务器地址,然后把配置文件安装到设备上。你可以使用Apple Configurator的导入功能导入这个配置文件然后修改,也可以直接用任何文本编辑器修改。

[info]Additional information about signed mobile config file. You can use this command to sign your mobileconfig file:
关于mobileconfig文件的签名,你可以用这个命令来给你的配置文件签名:
[/info]

openssl smime \
-sign \
-signer ssl.crt \
-inkey ssl.key \
-certfile ca.pem \
-nodetach \
-outform der \
-in MyProfile.mobileconfig \
-out Myprofile_signed.mobileconfig

[info]ssl.crt can be your domain cert or E-mail cert. ssl.key is the private key of the cert. ca.pem may need to let the device trust your own cert. In file and out file MUST be different!
ssl.crt可以是你域名的证书或者是E-mail证书。ssl.key是对应的私钥。有些设备可能需要ca.pem来进行证书信任的验证。输入和输出文件必须不同名!

About self-signed cert, please read this article:
自签名证书参考文章:
https://www.zeitgeist.se/2013/11/22/strongswan-howto-create-your-own-vpn/
[/info]

[info]If you want to see more things in IPSec’s log, you can add this in to your ipsec.conf:
如果你想在你的IPSec日志中看到更详细的信息,你可以在ipsec.conf文件中加入这句话:
charondebug="cfg 2, dmn 2, ike 2, net 2"
then the config file will look like this:
然后配置文件会变成这样:
config setup
charondebug = "cfg 2, dmn 2, ike 2, net 2"
uniqueids = no

Now restart ipsec and you will see more things in /var/log/syslog(or /var/log/daemon, /var/log/messages) about your ipsec vpn services.
现在重启ipsec服务,然后你就能在/var/log/syslog(或者 /var/log/daemon, /var/log/messages)中看到关于你的VPN服务的更多信息。

About charondebug, you can find official document hers:
关于charondebug参数,你可以在这里找到官方的文档:
https://wiki.strongswan.org/projects/strongswan/wiki/LoggerConfiguration

Normally, we just need level 2 log. Level 3 and above write some RAW date in hex which we may not need.
一般情况下我们只需要Level 2的日志。Level 3以上的日志包含一些我们可能不太需要的原始包信息。

After debug your vpn server, you may delete the charondebug line, or your log file’s size will grow very fast.
在你调试完你的VPN服务器之后,你最好删除charondebug这一行,不然你的日志文件会迅速增大。

Levels and Subsystems/Groups
The IKE daemon knows different numerical levels of logging, ranging from -1 to 4:

-1: Absolutely silent
0: Very basic auditing logs, (e.g. SA up/SA down)
1: Generic control flow with errors, a good default to see whats going on
2: More detailed debugging control flow
3: Including RAW data dumps in hex
4: Also include sensitive material in dumps, e.g. keys
Each logging message also has a source from which subsystem in the daemon the log came from:

app: applications other than daemons
asn: Low-level encoding/decoding (ASN.1, X.509 etc.)
cfg: Configuration management and plugins
chd: CHILD_SA/IPsec SA
dmn: Main daemon setup/cleanup/signal handling
enc: Packet encoding/decoding encryption/decryption operations
esp: libipsec library messages
ike: IKE_SA/ISAKMP SA
imc: Integrity Measurement Collector
imv: Integrity Measurement Verifier
job: Jobs queuing/processing and thread pool management
knl: IPsec/Networking kernel interface
lib: libstrongwan library messages
mgr: IKE_SA manager, handling synchronization for IKE_SA access
net: IKE network communication
pts: Platform Trust Service
tls: libtls library messages
tnc: Trusted Network Connect

[/info]

Xcode 4.1~4.6 + iOS 5、iOS 6免证书(iDP)开发+真机调试+生成IPA全攻略

开发环境使用的是目前为止最新的稳定版软件:Mac OS X Lion 10.7 + Xcode 4.1

目前Xcode 4.2 Preview版也已经发布,据说其修改方法跟4.1非常类似,只改动了一行代码,请参看参考文章的第二篇。本文仍以4.1版本为例。
更新:现在Xcode 4.2正式版和iOS 5均已发布,下面补充上4.2的修改方法。(2011-10-24)
各步骤会标明版本,比如(Xcode4.1请执行)和(Xcode4.2请执行),4.2.1的修改方法与4.2完全相同
未标明的步骤为两个版本均需执行的步骤!
更新:现在Xcode 4.3已发布,修改方法类似,Xcode 4.3的修改步骤将以(Xcode4.3请执行)标出(2012-2-7)
更新:现在Xcode 4.3.2和iOS 5.1.1完美越狱均已发布,本文及时进行了更新。修改方法类似,Xcode 4.3.2的修改步骤将以(Xcode4.3.2请执行)标出(2012-5-28)
更新:Mountain Lion + Xcode 4.4已发布,本人尚未安装,但在评论中看到已经有朋友测试成功,这里祝贺这些朋友!(2012年8月5日)
更新:Xcode 4.5 for Mountain Lion已发布。本人已经更新并亲测破解成功。Xcode 4.5将原来XML格式的plist文件变成了二进制格式,故修改方法略有不同,具体操作已在文中给出,请各位朋友测试!(2012年10月2日更新)
 
2012年2月7日更新:
目前本人已经测试并证实有效的平台有
Xcode 4.1:
iPod touch 4 iOS 4.3.3
 
Xcode 4.2:
iPod touch 4 iOS 4.3.3
iPod touch 4 iOS 5.0
iPod touch 4 iOS 5.0.1
 
Xcode 4.2.1:
iPod touch 4 iOS 4.3.3
iPod touch 4 iOS 5.0.1
iPhone 4S iOS 5.0.1(5A406)
 
Xcode 4.3(2012年2月7日更新)
iPhone 4S iOS 5.0.1(5A406)
 
Xcode 4.3.2(2012年5月28日更新)
iPhone 4S iOS 5.1.1
 
Xcode 4.4.1 for Mountain Lion(2012年9月26日更新)
iPhone 4S iOS 5.1.1
 
Xcode 4.5 for Mountain Lion(2012年10月2日更新)
iPhone 4S iOS 5.1.1
 
Xcode 4.6 for Mountain Lion(2013年2月12日更新)
iPhone 4S iOS 6.1
 
另外,操作系统的版本貌似对调试影响不大,这期间用过的系统有Mac OS X 10.6~10.8.2,都没有问题。
 
当然您需要先越狱您的设备并通过Cydia安装AppSync

本文参考了多篇文章,综合其中的方法,并修正其中的错误,整理而成。
未经许可,请勿转载。本文首次发表于http://kqwd.blog.163.com/
参考的文章有:
http://laolang.cn/back-end-develop/helloworld-iphone-developer.html
http://ccmos.tw/blog/2011/06/30/xcode4-port-program-to-idevice-without-idp/
http://www.cnblogs.com/flyingzl/articles/2207717.html
众所周知,在Xcode上开发的程序只能在模拟器中运行,如果要放到真机上则要花费99美金购买开发者证书iDP。这严重阻碍了我等草根开发者探索的脚步。写个小程序,同学间分享一下这个小小的愿望都不能满足,自然不能善罢甘休。
在没有iDP的情况下,要想将程序放到iPhone上调试,并最终发布IPA用于分享,需要以下几个步骤:
1.自己为自己颁发一个证书用于为生成的程序签名
2.修改工程配置以及Xcode的配置文件和二进制文件以阻止其验证和签名
3.通过自定义生成步骤,用伪造的证书为应用程序签名
4.使用一点小trick来生成IPA文件
1.创建证书
创建证书的过程比较简单,打开实用工具-钥匙串访问。然后在菜单栏里点击钥匙串访问-证书助理-创建证书来打开向导。第一个步骤比较重要,必须要把名称命名为iPhone Developer,将类型设定为代码签名,将”让我覆盖这些默认值”选中。之后的步骤无需更改,一路点击“确定”和“继续”来完成这个向导就可以。
1295629317816035869
2.修改Xcode的配置文件和二进制文件
下面的步骤稍微有点繁琐,您应该了解UNIX命令行的基本操作,并了解一种命令行文本编辑器,本文使用的是vim。尽管这里会给出完整的代码,但是关于修改和保存代码的基本操作,不再赘述。下面的操作请先将Xcode按Command+Q完全关闭
(1)修改配置文件
进入目录并备份原文件(4.1、4.2、4.3在这里主要的差别是SDK的目录名不同)
(Xcode4.1请执行)cd /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/
(Xcode4.2请执行)cd /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/
(Xcode4.3请执行)cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk
(Xcode4.3.2请执行)cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk
(Xcode4.5请执行)cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk
(Xcode4.6请执行)cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk
 
sudo cp SDKSettings.plist SDKSettings.plist.orig
进行编辑(除了Xcode 4.5之外的版本,包括Xcode 4.6)
sudo vim SDKSettings.plist
将以下两段中的YES改为NO
CODE_SIGNING_REQUIRED
YES
ENTITLEMENTS_REQUIRED
YES
Xcode 4.5的plist格式不是XML,而是改为了Apple自己的二进制格式,我们使用Xcode本身来编辑这个plist文件,命令是
sudo /Applications/Xcode.app/Contents/MacOS/Xcode ./SDKSettings.plist
会启动Xcode的图形界面,我们展开DefaultProperties分支,将下面的CODE_SIGNING_REQUIREDENTITLEMENTS_REQUIRED两个属性改为NO
下面修改另外一个文件
进入目录并备份原文件
(Xcode4.1/4.2请执行)cd /Developer/Platforms/iPhoneOS.platform/
(Xcode4.3/4.4/4.5/4.6请执行)cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
 
备份
sudo cp Info.plist Info.plist.orig
 
编辑文件
(Xcode4.1/4.2/4.3/4.4请执行)sudo vim Info.plist
将全部的XCiPhoneOSCodeSignContext 修改成 XCCodeSignContext,网上的大部分文章说有2处,但我找到了3处,可能是Xcode 4.1要多一处?(Xcode 4.2/4.3/4.3.2也有三处)总之都改掉了。提示:在在vim中输入/要搜索的内容来搜索,按n键是搜索下一处。
(Xcode 4.5/4.6)编辑命令如下
sudo /Applications/Xcode.app/Contents/MacOS/Xcode /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Info.plist
Xcode 4.5、4.6也有三处,分别在DefaultProperties分支下、RuntimeRequirements分支下和OverrideProperties分支下。
(2)二进制补丁
#在桌面上建立script这个脚本
cd ~/Desktop
vim script
#(Xcode 4.1执行)在编辑器中输入如下内容
#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=500 count=255
printf “xc3x26x00x00” >> working
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support
#(Xcode 4.2执行)在编辑器中输入如下内容
#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/PrivatePlugIns/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=500 count=255
printf “xc3x26x00x00” >> working
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support
保存并退出。(4.1和4.2在这里的区别也是目录名不同,就是代码中绿色的部分。4.1是Plug-ins而4.2是PrivatePlugIns
授予这个脚本执行权限并执行它
chmod 777 script
./script
正常的话应该输出(具体的数字可能有差别)
231+1 records in
231+1 records out
115904 bytes transferred in 0.001738 secs (66694555 bytes/sec)
#(Xcode 4.3注意)在Xcode 4.3版本中,我没有找到iPhoneOS Build System Support.xcplugin这个插件,因此我跳过了这个步骤,并且最终也成功的进行了联机调试。因此我个人认为Xcode 4.3没有必要执行“二进制补丁”这一步骤。请各位朋友测试~!
#(Xcode 4.3.2/4.4/4.5/4.6注意)在Xcode 4.3.2版本中,我们可以找到iPhoneOS Build System Support.xcplugin,但我没有修改它,仍然可以进行联机调试。这个修改步骤是从Xcode 3.X中继承过来的,我们有理由猜测,在Xcode 4.x版本中,已经不需要修改这个文件了。(2012年5月28日更新)
 
至此,对SDK中配置文件和二进制文件的修改就完成了
3.准备自定义的生成后脚本
连接互联网后执行
#(Xcode 4.1/4.2执行)
mkdir /Developer/iphoneentitlements401
cd /Developer/iphoneentitlements401
curl -O http://www.alexwhittemore.com/iphone/gen_entitlements.txt
mv gen_entitlements.txt gen_entitlements.py
chmod 777 gen_entitlements.py
 
#(Xcode 4.3/4.4/4.5/4.6执行)
mkdir /Applications/Xcode.app/Contents/Developer/iphoneentitlements
cd /Applications/Xcode.app/Contents/Developer/iphoneentitlements
curl -O http://www.alexwhittemore.com/iphone/gen_entitlements.txt
mv gen_entitlements.txt gen_entitlements.py
chmod 777 gen_entitlements.py
 
热心网友Ringo_D指出,这里可能涉及到权限问题。我做的时候貌似没有出啥问题,如果您在执行这段代码时遇到Permission denied提示的话,请将相应的语句前面加上sudo以获取超级权限。(2012年6月15日更新)
如果您已经联网,则请直接转到步骤4,如果您没有联网,那么请在相应目录手动创建gen_entitlements.py并授予其执行权限,这个文件的内容为
#!/usr/bin/env python
 
import sys
import struct
 
if len(sys.argv) != 3:
print “Usage: %s appname dest_file.xcent” % sys.argv[0]
sys.exit(-1)
 
APPNAME = sys.argv[1]
DEST = sys.argv[2]
 
if not DEST.endswith(‘.xml’) and not DEST.endswith(‘.xcent’):
print “Dest must be .xml (for ldid) or .xcent (for codesign)”
sys.exit(-1)
 
entitlements = “””
    application-identifier
    %s
    get-task-allow
   
“”” % APPNAME
 
f = open(DEST,’w’)
if DEST.endswith(‘.xcent’):
f.write(“\xfa\xde\x71\x71”)
f.write(struct.pack(‘>L’, len(entitlements) + 8))
f.write(entitlements)
f.close()
4.修改工程设置
特别注意:本阶段之前的修改配置文件、准备脚本等,只需要做一次。但本阶段的操作,对每个需要真机调试的工程都要做一遍。
这个步骤的主要作用是支持真机调试,如果不做这个步骤,仍然可以通过步骤5来生成ipa在真机上运行,但是无法使用Xcode内置的调试器对在真机上运行的程序进行单步跟踪。如果您的程序在点击Run真机调试时秒退,请检查此步骤是否正确完成。

(1)禁用Xcode自动的签名操作

将工程配置中所有的Code Signing选项全部设为Don’t Code Sign,如图。可能需要先点击“All”让这个选项显示出来
2529052665762129796
(2)添加自定义的生成后脚本
在Build Phases中添加一个Phase,右下角的Add Build Phase,然后单击Add Run Script,输入以下脚本
(对于Xcode 4.1/4.2)
export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
if [ “${PLATFORM_NAME}” == “iphoneos” ] || [ “${PLATFORM_NAME}” == “ipados” ]; then
/Developer/iphoneentitlements401/gen_entitlements.py “my.company.${PROJECT_NAME}” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent”;
codesign -f -s “iPhone Developer” –entitlements “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/”
fi
(对于Xcode 4.3/4.4/4.5/4.6)
export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
if [ “${PLATFORM_NAME}” == “iphoneos” ] || [ “${PLATFORM_NAME}” == “ipados” ]; then
/Applications/Xcode.app/Contents/Developer/iphoneentitlements/gen_entitlements.py “my.company.${PROJECT_NAME}” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent”;
codesign -f -s “iPhone Developer” –entitlements “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/”
fi
 
如图所示:
672162244401931959
至此配置全部完成,下面就可以插上iPhone,重新选择生成目标来测试一下在线调试了!如果是第一次使用该设备调试,请先在Organizer中将设备切换为开发模式,具体操作请见常见问题5。
5.旁门左道生成IPA文件
如果我的程序调试好了,怎么才能发给别人用呢?正常情况下IPA文件是从Xcode的Organizer中输出的,但是我们没有证书,这样输出会产生错误。我们只能用个小trick来完成这个操作了。
先将代码生成为Release目标,然后打开工程的输出文件夹,通常情况下这个目录是
/Users/你的用户名/Library/Developer/Xcode/DerivedData/以工程名打头的文件夹/Build/Products/Release-iphoneos
很纠结吧~这个目录下有个.app的文件,就是生成的程序了。把这个.app拖到iTunes中,它会出现在应用程序那个列表中,然后再把它从iTunes的那个列表中拖出来(比如拖到桌面),发生了什么?哈哈,它就这样变成.ipa了!
把这个.ipa发给朋友,大家就可以跟您一起分享这个程序了。
文章发表以来点击量已经超过了5000次,也收到了不少热心博友的反馈和疑问。现加以整理,列为常见问题。感谢大家的关注!(2011年12月2日)
常见问题:
不成功的先看这里!!本文点击量超过6000,无数网友亲测成功,如果您失败了基本可以确定是您没有严格按照文中的方法操作,下面列出常见问题,切望各位朋友提问前先看看!!(2011年12月14日)
 
1. 我是初学者,请问什么是权限?执行权限(x权限)是什么意思?什么是脚本?如何加执行权限?sudo是什么命令?vim是什么,如何在vim中保存更改?你说的目录我没找到怎么办?我有些步骤没看明白,能不能加QQ交流?
解答:首先感谢您关注我的博客。这里要提醒各位初学者朋友,Xcode提供了非常完善的模拟器调试环境,模拟器调试要比真机调试方便得多,也简单得多,使用模拟器调试程序是iOS开发的常态。真机调试通常是在产品快要完工时才进行的,看一下程序在实际机器上的视觉效果等等。还有依赖于加速度计的程序要测试一下加速度计的程序有没有问题。所以初学者并不需要一开始就进行真机调试。初学者配置真机调试的主要目的可能并非学习技术,而是满足好奇心、追求成就感甚至是为了向朋友炫耀等等。而这些目的并不值得您花费这么大的精力来阅读本文。
因此本文是给有一定基础的朋友看的,各种命令是免不了的。UNIX中的基本命令比如cp,mv,cd,chmod,sudo啥的还有vim编辑器,如果您都没听说过,强烈建议您不要尝试本文提到的修改。一旦改错了轻则Xcode挂掉,重则系统崩溃。如果遇到解决不了的问题欢迎留言询问,务必给出详细的错误信息,否则无法判断。博主恕不解答类似于如何执行脚本代码,如何赋予执行权限,如何使用vim编辑器(如何保存)等与iOS开发无关的UNIX基础问题。博主非常乐意以文会友,结识有思想、有创意、有技术的大牛。博主也会不定时到博客上对热心网友提出的问题进行简单的解答。但并没有充足的时间通过QQ对文中的步骤进行手把手的解释和指导。这里先向有这种需求的朋友说声抱歉了!
 
2. 各种错误,错误信息中包含“No such file or directory”这句话
解答:错误信息的含义非常清楚,就是“没有这个文件或者目录”。这类错误通常是由于您拷贝代码时不全或者开发环境安装错误等问题导致的。请再次检查报错的目录是否存在,检查代码与本文给出的是否严格一致,各种检查吧~总之是低级错误
 
3. 联机调试时程序秒退,或者无法安装到设备,或者任何时候报错,错误信息中包含“code signing”、“CERT”、“signature”或者“certificate”字样的(最常见的错误!!)
解答:证书错误或者签名错误,这种问题就不要问了,肯定是因为您没有严格文中的步骤做。提醒您检查的地方有(1)有没有设置为Don’t Code signing (2)生成后事件的代码是否已经正确粘贴 (3)那个Python脚本是否已经成功执行 (4)设备是否已经越狱并安装AppSync (5)第一步的iPhone Developer证书是否已经正确创建
其中最可能出问题的就是生成后事件代码(文中的那个Run Script)没有正确执行。可能是您忘记了添加Run Script并粘贴那段代码,也可能是您没复制全,或者复制到了啥特殊字符导致执行出错。查看那个script的执行结果的方法是在Xcode左侧的侧边栏里,点最靠右的一个标签(Show the Log navigator),看最近的一个Build日志(不是Debug日志),找到一行Run custom shell script “Run Script”那一行,正常情况下那一行跟其他行一样,是不能展开的。如果那一行左边有个小箭头,点击后能展开的话,说明执行出错,展开后的信息即为出错的信息。请认真查看错误信息并修正脚本中的错误。如果Build日志里根本没有Run custom shell script “Run Script”,那说明您忘记添加Build script了。。。(2012年2月9日更新)
补充:Run Script经常报的一条错误是“replacing existing signature”。。。这个提示的意思是“替换已有的签名”,出现这个提示的原因是,你并没有成功的阻止Xcode使用默认的方法为应用程序签名。因为这个破解的原理就是阻止Xcode为app签名,而用script中的自定义过程手动为app签名。当script为app签名时,发现app已经被Xcode签名过了,就会报这个错误。出这个错误后提醒您检查的地方有两个(1)SDKSettings.plist中需要修改的地方是否已经正确修改 (2)工程设置里是否将那5个签名的选项全部设为Don’t Code signing (2012年6月15日更新)
 
4. iPad能用吗?
解答:我没有iPad,所以没法准确回答。但从热心博友的回复来看,iPad无疑是可以用的。
如果要用ipad 需要把第四步脚本文件里的 platform_name == iphones 换成platform_name == ipads 不然会报错的~ (感谢博友xyishao的建议)
感谢qingcheng89提出的改进意见,现在来看上述代码可以直接支持iPad而无需修改,请各位朋友测试。(2012年2月9日更新)
 
5. 为什么我的Build for Archiving选项是灰色的?
解答:是因为您没有把设备插到电脑上。虽然这个问题挺蠢的,但我曾经也有过这个疑问,哈哈~~ 
经热心网友xc7296815提醒,设备未开启开发模式也会导致Build for Archiving不可用。开启开发模式的方法是:插上设备,点Xcode右上角的Organizer图标,选中您的设备,看一下设备名称左侧的小灯是什么颜色的。若是灰色代表未开启开发模式。此时在右边窗口中点击“Use for Development” 即可。若是黄色请重新插拔设备,若是绿色代表设备已经开启开发模式(2011年12月25日)
关于启用开发模式的补充:点击Use for Development后,会要求输入Apple ID,这里点击取消即可。这时启用设备开发模式的进程会立即终止。设备名称旁边应该有一个黄灯。此时重新插拔设备,Organizer中会出现一个进度条,等这个进度条跑完,小灯就会变成绿色,开发模式已经启用。(2012年5月28日更新)
再补充:最近经常有人提问说,无论怎么搞,Organizer中的灯始终是黄色的。这种情况几乎可以百分之百的确定是您的Xcode版本不够高。如果您的设备是iOS 5.1.1,则必须使用Xcode 4.3.2或以上版本。同样的道理,iOS 5.0.1对应Xcode 4.3.1,iOS 5.0对应Xcode 4.3……(2012年6与5日更新)
 
6.我的iOS版本/Xcode版与你的不同,能用吗?
解答:本人测试过的环境和设备已经在文章开头给出。其他环境我没有测试过,也没有条件测试,因此当您的环境与我的不同时,别问我可不可用,您可以试一下,然后把结果告诉我,也为其他的网友提供方便,在此先谢谢您了!
 
7.真机调试时出现Error launching remote program: failed to get the task for process xxx错误(2012年1月26日更新)
解答:我在调试中貌似没有遇到过这个问题,但是不少网友指出会有这个问题,谁来告诉我什么情况下会出这个问题呢?如果您遇到了这个问题,请阅读Apple官方的帮助文档http://developer.apple.com/library/ios/#qa/qa1710/_index.html
2012年2月1日更新:有网友指出该错误是由于权限设置错误导致的。由于我使用了跟报错的那位网友完全相同的环境,而在操作过程中并没有遇到这个错误,所以基本可以确定是您没有按步骤操作造成的,请您再次检查整个过程,尤其是热心网友提出的下载脚本并修改执行权限的部分。
经本人测试,如果该错误出现在编译运行之后,且现象为设备上的程序闪退,则是由于签名错误导致的,这是由于您没有严格按照上述步骤来做导致的,请参考常见问题3.(2012年2月9日更新)
文章好长…欢迎各路大侠指正。

越狱检测/越狱检测绕过—xCon

一直忽略了越狱检测与越狱检测绕过的问题,因为我认为在app争抢装机率的环境下,是不会在乎对方的设备越狱与否的。但很显然,我忽略了一个问题,app在设计的时候或许会依照设备是否越狱而采取不同的流程,比如说对越狱的设备采取更多的安全措施,在这种场景下,越狱检测是否可靠就成为了关键问题。本篇文章主要介绍越狱检测的常见方法(并配有相应的测试代码),以及最流行的越狱检测绕过插件xCon(会分析该工具会绕过哪些检测方法),最后总结了个人认为的比较可靠的越狱检测方法。

一、越狱检测

(一)《Hacking and Securing iOS Applications》这本书的第13章介绍了以下方面做越狱检测
1. 沙盒完整性校验
根据fork()的返回值判断创建子进程是否成功
(1)返回-1,表示没有创建新的进程
(2)在子进程中,返回0
(3)在父进程中,返回子进程的PID
沙盒如何被破坏,则fork的返回值为大于等于0.
我在越狱设备上,尝试了一下,创建子进程是失败,说明不能根据这种方法来判断是否越狱。xCon对此种方法有检测
代码如下:
1344605963764714110

2. 文件系统检查
(1)检查常见的越狱文件是否存在
以下是最常见的越狱文件。可以使用stat函数来判断以下文件是否存在

/Library/MobileSubstrate/MobileSubstrate.dylib 最重要的越狱文件,几乎所有的越狱机都会安装MobileSubstrate

/Applications/Cydia.app/ /var/lib/cydia/绝大多数越狱机都会安装

/var/cache/apt /var/lib/apt /etc/apt

/bin/bash /bin/sh

/usr/sbin/sshd /usr/libexec/ssh-keysign /etc/ssh/sshd_config

代码如下

6597697587796059517

(1)返回0,表示指定的文件存在
(2)返回-1,表示执行失败,错误代码存于errno中
错误代码:
ENOENT         参数file_name指定的文件不存在
ENOTDIR        路径中的目录存在但却非真正的目录
ELOOP          欲打开的文件有过多符号连接问题,上限为16符号连接
EFAULT         参数buf为无效指针,指向无法存在的内存空间
EACCESS        存取文件时被拒绝
ENOMEM         核心内存不足
ENAMETOOLONG   参数file_name的路径名称太长
struct stat {
dev_t         st_dev;       //文件的设备编号
ino_t         st_ino;       //节点
mode_t        st_mode;      //文件的类型和存取的权限
nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
uid_t         st_uid;       //用户ID
gid_t         st_gid;       //组ID
dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
off_t         st_size;      //文件字节数(文件大小)
unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks;    //块数
time_t        st_atime;     //最后一次访问时间
time_t        st_mtime;     //最后一次修改时间
time_t        st_ctime;     //最后一次改变时间(指属性)
};
该方法最简单,也是流程最广的,但最容易被破解。在使用该方法的时候,注意使用底层的c函数 stat函数来判断以下路径名,路径名做编码处理(不要使用base64编码),千万不要使用NSFileManager类,会被hook掉

 

(2) /etc/fstab文件的大小
该文件描述系统在启动时挂载文件系统和存储设备的详细信息,为了使得/root文件系统有读写权限,一般会修改该文件。虽然app不允许查看该文件的内容,但可以使用stat函数获得该文件的大小。在iOS 5上,未越狱的该文件大小未80字节,越狱的一般只有65字节。
代码如下
6597704184865825988
在安装了xCon的越狱设备上运行,result的大小为803705776 ;卸载xCon后在越狱设备上运行,result的大小为66
个人觉得该方法不怎么可靠,并且麻烦,特别是在app在多个iOS版本上运行时。xCon对此种方法有检测,不能采用这种办法
(3)检查特定的文件是否是符号链接文件
iOS磁盘通常会划分为两个分区,一个只读,容量较小的系统分区,和一个较大的用户分区。所有的预装app(例如appstore)都安装在系统分区的/Application文件夹下。在越狱设备上,为了使得第三方软件可以安装在该文件夹下同时又避免占用系统分区的空间,会创建一个符号链接到/var/stash/下。因此可以使用lstat函数,检测/Applications的属性,看是目录,还是符号链接。如果是符号链接,则能确定是越狱设备。
以下列出了一般会创建符号链接的几个文件,可以检查以下文件
6598150586586535859

代码如下:

6597655806354205806
没有检测过未越狱设备的情况,所以不好判断该方法是否有效
(二)http://theiphonewiki.com/wiki/index.php?title=Bypassing_Jailbreak_Detection 给出了以下6种越狱监测方法
1、检测特定目录或文件是否存在
检测文件系统是否存在越狱后才会有的文件,例如/Applications/Cydia.app, /privte/var/stash
一般采用NSFileManager类的- (BOOL)fileExistsAtPath:(NSString *)path方法(很容易被hook掉)
或者采用底层的C函数,例如fopen(),stat() or access()
《Hacking and Securing iOS Applications》的方法2文件系统检查相同
xCon对此种方法有检测
2、检测特定目录或文件的文件访问权限
检测文件系统中特定文件或目录的unix文件访问权限(还有大小),越狱设备较之未越狱设备有太多的目录或文件具备写权限
一般采用NSFileManager类的- (BOOL)isWritableFileAtPath:(NSString *)path(很容易被hook掉)
或者采用底层的C函数,例如statfs()
xCon对此种方法有检测
3、检测是否能创建子进程
检测能否创建子进程,在非越狱设备上,由于沙箱保护机制,是不允许进程的
可以调用一些会创建子进程的C函数,例如fork(),popen()
《Hacking and Securing iOS Applications》的方法1沙盒完整性检查相同
xCon对此种方法有检测
4、检测能否执行ssh本地连接
检测能否执行ssh本地连接,在绝大多数的非越狱设备上,一般会安装OpenSSH(ssh服务端),如果能检测到ssh 127.0.0.1 -p 22连接成功,则说明为越狱机
xCon对此种方法有检测
5、检测system()函数的返回值
检测system()函数的返回值,调用sytem()函数,不要任何参数。在越狱设备上会返回1,在非越狱设备上会返回0
sytem()函数如果不要参数会报错
6597409515750961892
6、检测dylib(动态链接库)的内容

这种方法是目前最靠谱的方法,调用_dyld_image_count()和_dyld_get_image_name()来看当前有哪些dylib被加载

测试结果:
使用下面代码就可以知道目标iOS设备加载了哪些dylib

#include

#import

#import

#import


void printDYLD()

{

//Get count of all currently loaded DYLD


uint32_t count = _dyld_image_count();


for(uint32_t i = 0; i < count; i++)


{


//Name of image (includes full path)


const char *dyld = _dyld_get_image_name(i);

//Get name of file


int slength = strlen(dyld);

 

int j;


for(j = slength – 1; j>= 0; –j)


if(dyld[j] == ‘/’) break;

 

printf(“%s\n”,  dyld);


}


printf(“\n”);


}


int main(int argc, char *argv[])

{


printDYLD();

 

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];


int retVal = UIApplicationMain(argc, argv, nil, nil);


[pool release];


return retVal;


}

下图显示了我的iOS设备当前加载的dylib的路径,最下面就可以看到xCon

6597237991936914762
此种方法存在一个问题,是否能通过app store审核呢?
二、越狱检测绕过——xCon
可以从Cydia中安装,是目前为止最强大的越狱检测工具。由n00neimp0rtant与Lunatik共同开发,它据说patch了目前所知的所有越狱检测方法(也有不能patch的应用)。估计是由于影响太大了,目前已不开放源码了。
安装xCon后,会有两个文件xCon.dylib与xCon.plist出现在设备/Library/MobileSubstrate/DynamicLibraries目录下
(1)xCon.plist
该文件为过滤文件,标识在调用com.apple.UIKit时加载xCon.dylib
6597805339935558059
(2) xCon.dylib
可以使用otool工具将该文件的text section反汇编出来从而了解程序的具体逻辑(在windows下可以使用IDA Pro查看)

DANI-LEE-2:iostools danqingdani$ otool -tV xCon.dylib >xContextsection

可以根据文件中的函数名,同时结合该工具的原理以及越狱检测的一些常用手段(文章第一部分有介绍)来猜其逻辑,例如越狱检测方法中的文件系统检查,会根据特定的文件路径名来匹配,我们可以使用strings查看文件中的内容,看看会有哪些文件路径名。

DANI-LEE-2:IAP tools danqingdani$ strings xCon.dylib >xConReadable

以下是xCon中会匹配的文件名

/usr/bin/sshd
/usr/libexec/sftp-server
/usr/sbin/sshd

/bin/bash
/bin/sh
/bin/sw
/etc/apt
/etc/fstab
/Applications/blackra1n.app
/Applications/Cydia.app
/Applications/Cydia.app/Info.plist
/Applications/Cycorder.app
/Applications/Loader.app
/Applications/FakeCarrier.app
/Applications/Icy.app
/Applications/IntelliScreen.app
/Applications/MxTube.app
/Applications/RockApp.app
/Applications/SBSettings.app
/Applications/WinterBoard.app
/bin/bash/Applications/Cydia.app
/Library/LaunchDaemons/com.openssh.sshd.plist
/Library/Frameworks/CydiaSubstrate.framework
/Library/MobileSubstrate
/Library/MobileSubstrate/
/Library/MobileSubstrate/DynamicLibraries
/Library/MobileSubstrate/DynamicLibraries/
/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist
/Library/MobileSubstrate/DynamicLibraries/Veency.plist
/Library/MobileSubstrate/DynamicLibraries/xCon.plist
/private/var/lib/apt
/private/var/lib/apt/
/private/var/lib/cydia
/private/var/mobile/Library/SBSettings/Themes
/private/var/stash
/private/var/tmp/cydia.log
/System/Library/LaunchDaemons/com.ikey.bbot.plist
/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist

NzI0MS9MaWJyYXJ5L01vYmlsZVN1YnN0cmF0ZQ==  (对应7241/Library/MobileSubstrate)

通过分析,xCon会绕过以下越狱检测方法

(1)    根据是否存在特定的越狱文件,及特定文件的权限是否发生变化来判断设备是否越狱

 

 

fileExistsAtPath:

fileExistsAtPath:isDirectory:

filePermission:

fileSystemIsValid:

checkFileSystemWithPath:forPermissions:

mobileSubstrateWorkaround

detectIllegalApplication:

(2)       根据沙箱完整性检测设备是否越狱

canUseFork

(3)       根据文件系统的分区是否发生变化来检测设备是否越狱

partitionsModified

(4)       根据是否安装ssh来判断设备是否越狱

ssh root@127.0.0.1

 

三、总结
总之,要做好越狱检测,建议使用底层的c语言函数进行,用于越狱检测的特征字符也需要做混淆处理,检测函数名也做混淆处理。第一部分介绍的以下三种方法,可以尝试一下
(1)检查常见的越狱文件是否存在,使用stat(),检查以下文件是否存在

/Library/MobileSubstrate/MobileSubstrate.dylib 最重要的越狱文件,几乎所有的越狱机都会安装MobileSubstrate

/Applications/Cydia.app/ /var/lib/cydia/绝大多数越狱机都会安装

/var/cache/apt /var/lib/apt /etc/apt

/bin/bash /bin/sh

/usr/sbin/sshd /usr/libexec/ssh-keysign /etc/ssh/sshd_config

(2)检查特定的文件是否是符号链接文件,使用lstat(),检查以下文件是否为符号链接文件

/Applications

/Library/Ringtones

/Library/Wallpaper

/usr/include

/usr/libexec

/usr/share

   (3)检差dylib(动态链接库)的内容,使用_dyld_image_count与_dyld_get_image_name,检查是否包含越狱插件的dylib文件

参考:
http://theiphonewiki.com/wiki/index.php?title=XCon
http://theiphonewiki.com/wiki/index.php?title=Bypassing_Jailbreak_Detection