所谓“反向共享”,就是电脑连接上网络,iPhone 没有,然后把网络连接共享给 iPhone。
网上有一些方案是利用代理服务器的,不完美,这里利用的是 OpenVPN,可以说是 90% 完美了。
为了避免伸手党(其实是我自己懒得写),我就不说详细了,把大概的内容说一下。如果谁感兴趣可以写一份更详细的教程。
- 为什么需要反向网络共享?你可能在一个没有 Wi-Fi 接入的地方(或者你的机器是行货 3GS 无 Wi-Fi),然后想向 iPhone 里下载一些东西,这个时候反向共享就有用了。
-
iPhone 端安装软件首先,你的 iPhone 必须越狱(
废话),然后从 Cydia 安装这些包:openssh GuizmOVPN如果你找不到 openssh 请把身份设置成“开发者”,后面那个是收费的,可以下载免费试用版,我们不需要主程序,只需要里面打过特殊补丁的 OpenVPN 客户端。2015年1月1日更新:请不要升级 GuizmOVPN 到 1.2.1!因为它将 TUNEMU 换成了 UTUN,因而不能工作!幸好我有备份:com.guizmo.openvpn_1.2.0_iphoneos-arm.deb至于怎么安装我就不说了,有 2G/3G/4G 的连上网下。没有的可以用 Cyder 2。截至发文,Cyder 2 仍然没有支持 iOS 5 以上系统,所以可以用 Cyder 下载 deb 包及其依赖,然后用 i-FunBox 拷贝进 iPhone 的 Cyder 自动安装目录。如果你打算用命令行 apt-get install,请用下面的软件包名:openssh com.guizmo.openvpn - 电脑端安装软件你需要这些:openssh openvpn usbmuxd 你可能还想要 libimobiledevice ifuse根据发行版不同,你用的发行版可能是别的名字。
- 配置 OpenVPN怎么生成证书不在本文讨论的范畴(Google is your friend)。下面我们来讨论特殊的地方。假设你已经生成好 ca.crt ca.key dh1024.pem server.crt server.key client.crt client.key 了。我们来写 server.ovpn:local 127.0.0.1port 1194proto tcpdev tunca ca.crtcert server.crtkey server.keydh dh1024.pemserver 10.8.0.0 255.255.255.0push "dhcp-option DNS 8.8.8.8"push "dhcp-option DNS 8.8.4.4"client-to-clientduplicate-cnkeepalive 10 120verb 3然后是 client.ovpn:clientdev tunproto tcpremote localhost 1194nobindpersist-keypersist-tunca ca.crtcert client.crtkey client.keyns-cert-type serververb 3up ./guizmovpn_updown.shdown ./guizmovpn_updown.sh然后是关键的 guizmovpn_updown.sh,这个文件应该在 /Applications/GuizmOVPN.app 有。但是我的这个版本貌似可以用,如果你的版本不能用,试试看我的:
#!/bin/bash ####################### # GuizmOVPN_updown.sh # # Version 1.0.6 # ####################### function CopyKey { if [ "`KeyExists $1`" == "NO" ] ; then return fi source=$1; dest=$2; error="0"; echo "d.init" >/tmp/tmpscutil for param in `echo "show $1" | /usr/sbin/scutil | grep -v "<dictionary>" | tr -d '\n' | tr '}' '\n' | awk '{ print $1 }'` ; do value=`echo "show $1" | /usr/sbin/scutil| grep -v "<dictionary>" | tr -d '\n' | tr '}' '\n' | grep $param` if $( echo $value | grep --quiet '<array>' ) ; then unset array_val for arraynum in 2 3 4 5 6 7 8 9 ; do val=`echo $value | cut -d '{' -f 2 | cut -d ':' -f $arraynum | cut -d ' ' -f 2` if [ "$val" != "" ] ; then array_val[$(($arraynum-1))]=$val; fi done if [ ${#array_val[@]} ]; then echo "d.add $param * ${array_val[*]}" >>/tmp/tmpscutil else error="1" fi else val=`echo "$value" | awk '{ print $3 }'` if [ "`echo "$val" | tr -d ' '`" == "" ] ; then error="1"; else echo "d.add $param $val" >>/tmp/tmpscutil fi fi done echo "set $dest" >>/tmp/tmpscutil if [ "$error"=="0" ] ; then cat /tmp/tmpscutil | /usr/sbin/scutil else echo "Error reading key $1" fi } function GetActualDNS { OLDDNS=`echo "show State:/Network/Service/$1/DNS" | /usr/sbin/scutil | grep -A 1 "ServerAddresses : " | grep "0 : " | awk '{print $3}' | tr -d " "` echo $OLDDNS } function KeyExists { if [ "`echo "show $1" | /usr/sbin/scutil | tr -d " "`" == "Nosuchkey" ] ; then echo "NO" ; else echo "YES" ; fi } PSID=$( (/usr/sbin/scutil | grep PrimaryService | sed -e 's/.*PrimaryService : //')<< EOF open get State:/Network/Global/IPv4 d.show quit EOF ) case "$script_type" in up) # Stop the APSd #/bin/launchctl unload /System/Library/LaunchDaemons/com.apple.apsd.plist # Remove informations about a previous connection echo "remove State:/Network/Service/OpenVPN/DNS" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/IPv4" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/PPP" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/PSID" | /usr/sbin/scutil >/dev/null 2>&1 # Check if we need to handle DNSPush unset dns unset domain if [ "$DNSPush" == "Y" ] ; then # Store the PSID that we modify, in order to restore the correct one on disconnection if [ "$PSID" != "" ] ; then echo "d.init" >/tmp/tmpscutil echo "d.add PSID $PSID" >>/tmp/tmpscutil echo "set State:/Network/Service/OpenVPN/PSID" >>/tmp/tmpscutil cat /tmp/tmpscutil | /usr/sbin/scutil fi # Save the DNS settings # If it has already been set, don't save it again if [ "`KeyExists State:/Network/Global/DNSold`" == "NO" ] ; then CopyKey Setup:/Network/Service/$PSID/DNS Setup:/Network/Service/$PSID/DNSold ; CopyKey State:/Network/Service/$PSID/DNS State:/Network/Service/$PSID/DNSold ; CopyKey State:/Network/Global/DNS State:/Network/Global/DNSold ; fi n=1; i=0; j=0; while o=foreign_option_${n}; o=${!o}; [ "$o" ] do case $o in 'dhcp-option DNS '*) dns[i++]=${o/dhcp-option DNS /};; 'dhcp-option DOMAIN '*) domain[j++]=${o/dhcp-option DOMAIN /} ;; esac; let n++ done # Check if we need to try to keep local DNS if [ "$DNSKeep" == "Y" ] ; then # If DNS push has been set, add the actual DNS in the list, in case the DNS pushed don't respond if [ $i != 0 ] && [ $i -le 3 ] ; then dns[i]=`GetActualDNS $PSID`; # Check if the DNS is different from the gateway IP. # If it's the case, add a route to it if [ "$traffic_is_redirected" == "1" ] && [ "$dns[i]" != "" ] && [ "$route_net_gateway" != "${dns[i]}" ] && [ "$route_net_gateway" != "" ] ; then echo "Add a route to ${dns[i]} with gateway $route_net_gateway" ; /sbin/route add -net ${dns[i]} $route_net_gateway 255.255.255.255; fi fi fi if [ "${dns[0]}" != "" ] ; then echo "Setting DNS to /Network/Service/$PSID/DNS (${dns[*]})" echo "d.init" >/tmp/tmpscutil echo "d.add ServerAddresses * ${dns[*]}" >>/tmp/tmpscutil if [ "${domain[0]}" != "" ] ; then echo "Setting domain to /Network/Service/$PSID/DNS (${domain[*]})" echo "d.add SupplementalMatchDomains * ${domain[*]}" >>/tmp/tmpscutil fi echo "set State:/Network/Service/$PSID/DNS" >>/tmp/tmpscutil cat /tmp/tmpscutil | /usr/sbin/scutil # For a strange reason, some devices don't use the "State" but the "Setup", so we copy the key. if [ "`KeyExists Setup:/Network/Service/$PSID/DNS`" == "YES" ] ; then CopyKey State:/Network/Service/$PSID/DNS Setup:/Network/Service/$PSID/DNS fi CopyKey State:/Network/Service/$PSID/DNS State:/Network/Service/OpenVPN/DNS CopyKey State:/Network/Service/$PSID/DNS State:/Network/Global/DNS fi fi # Add informations about the connection # IPv4 echo "d.init" >/tmp/tmpscutil echo "d.add DestAddresses * $trusted_ip" >>/tmp/tmpscutil echo "d.add ServerAddress $trusted_ip" >>/tmp/tmpscutil echo "d.add InterfaceName ppp0" >>/tmp/tmpscutil echo "d.add Addresses * $ifconfig_local" >>/tmp/tmpscutil echo "d.add SubnetMasks * 255.255.255.255" >>/tmp/tmpscutil echo "d.add NetworkSignature VPN.RemoteAddress=$trusted_ip" >>/tmp/tmpscutil echo "set Setup:/Network/Service/OpenVPN/IPv4" >>/tmp/tmpscutil echo "set State:/Network/Service/OpenVPN/IPv4" >>/tmp/tmpscutil # PPP echo "d.init" >>/tmp/tmpscutil echo "d.add Status 8" >>/tmp/tmpscutil echo "d.add InterfaceName ppp0" >>/tmp/tmpscutil echo "set Setup:/Network/Service/OpenVPN/PPP" >>/tmp/tmpscutil echo "set State:/Network/Service/OpenVPN/PPP" >>/tmp/tmpscutil # Interface echo "d.init" >>/tmp/tmpscutil echo "d.add Type PPP" >>/tmp/tmpscutil echo "d.add SubType OpenVPN" >>/tmp/tmpscutil echo "set Setup:/Network/Service/OpenVPN/Interface" >>/tmp/tmpscutil cat /tmp/tmpscutil | /usr/sbin/scutil # Add infos about connection to be displayed in GUI /Applications/GuizmOVPN.app/tools writeprefs InfosIPAddress "$ifconfig_local" if [ "$ifconfig_netmask" == "" ] ; then /Applications/GuizmOVPN.app/tools writeprefs InfosSubnetMask "255.255.255.255" /Applications/GuizmOVPN.app/tools writeprefs InfosGateway "$ifconfig_remote" else /Applications/GuizmOVPN.app/tools writeprefs InfosSubnetMask "$ifconfig_netmask" /Applications/GuizmOVPN.app/tools writeprefs InfosGateway "$InfosGateway" fi /Applications/GuizmOVPN.app/tools writeprefs InfosTrafficRedirected "$traffic_is_redirected" # Start the APSd #/bin/launchctl load /System/Library/LaunchDaemons/com.apple.apsd.plist ;; down) # Remove the connection infos /Applications/GuizmOVPN.app/tools writeprefs InfosIPAddress "" /Applications/GuizmOVPN.app/tools writeprefs InfosSubnetMask "" /Applications/GuizmOVPN.app/tools writeprefs InfosGateway "" /Applications/GuizmOVPN.app/tools writeprefs InfosTrafficRedirected "" # Check if we have a stored PSID. If not, take the actual one OLD_PSID=`echo "show State:/Network/Service/OpenVPN/PSID" | /usr/sbin/scutil | grep PSID | awk '{print $3}'` if [ "$OLD_PSID" == "" ] ; then OLD_PSID=$PSID fi # If we have saved DNS, restore them if [ "$OLD_PSID" != "" ] && [ "`KeyExists State:/Network/Global/DNSold`" == "YES" ] ; then echo "Restoring DNS to $OLD_PSID"; CopyKey Setup:/Network/Service/$OLD_PSID/DNSold Setup:/Network/Service/$OLD_PSID/DNS ; CopyKey State:/Network/Service/$OLD_PSID/DNSold State:/Network/Service/$OLD_PSID/DNS ; CopyKey State:/Network/Global/DNSold State:/Network/Global/DNS ; echo "remove Setup:/Network/Service/$OLD_PSID/DNSold" | /usr/sbin/scutil >/dev/null 2>&1 ; echo "remove State:/Network/Service/$OLD_PSID/DNSold" | /usr/sbin/scutil >/dev/null 2>&1 ; echo "remove State:/Network/Global/DNSold" | /usr/sbin/scutil >/dev/null 2>&1 ; fi # Check if we need to remove the route we added for the DNS if [ "$traffic_is_redirected" == "1" ] && [ "$route_net_gateway" != "`GetActualDNS $OLD_PSID`" ] && [ "$route_net_gateway" != "" ] && [ "`GetActualDNS $OLD_PSID`" != "" ] ; then echo "Removing route to `GetActualDNS $OLD_PSID` with gateway $route_net_gateway" /sbin/route delete -net `GetActualDNS $OLD_PSID` $route_net_gateway 255.255.255.255 fi # Remove informations about the connection echo "remove State:/Network/Service/OpenVPN/DNS" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/IPv4" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/PPP" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove State:/Network/Service/OpenVPN/PSID" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove Setup:/Network/Service/OpenVPN/IPv4" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove Setup:/Network/Service/OpenVPN/PPP" | /usr/sbin/scutil >/dev/null 2>&1 echo "remove Setup:/Network/Service/OpenVPN/Interface" | /usr/sbin/scutil >/dev/null 2>&1 ;; *) echo "$0: invalid script_type $script_type" && exit 1 ;; esac #####
- 启动脚本我们来写一个启动脚本吧,connect.sh#!/bin/shsudo -vsudo usbmuxdiproxy 2222 22 &sudo -n openvpn --config server.ovpn &sleep 1exec ssh root@localhost -p 2222 -R 1194:localhost:1194 /var/root/iptether/ovpncon.sh然后是 iPhone 端的启动脚本 ovpncon.sh#!/bin/sh(cd /var/root/iptether; /Applications/GuizmOVPN.app/openvpn --config client.ovpn --script-security 2) &还有 DNS 修复脚本,一般情况下是不需要的,但如果 DNS 不工作,就试试看 iPhone 端执行 ovpndns.sh:#!/bin/sh/usr/sbin/scutil << EOFopend.initd.add ServerAddresses * 8.8.8.8 8.8.4.4set State:/Network/Service/OpenVPN/DNSquitEOF
- 配置 NAT 转发echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward但是这会在关机后失效。如果希望下次开机自动开启转发,再修改 /etc/sysctl.conf:net.ipv4.ip_forward = 1然后配置防火墙:sudo iptables -t nat -A POSTROUTING -j MASQUERADE同样,这个也是关机后丢失,如果想要保留,再修改 /etc/iptables/iptables.rules 并且开启系统的 iptables 服务(可能会因发行版而不同):*nat-A POSTROUTING -j MASQUERADECOMMIT
- Copy & Run!现在,把一大堆 OpenVPN 的配置文件和证书文件用 SCP 拷贝到 iPhone 的 /var/root/iptether 里面,用户名 root,密码 alpine(如果你没有修改,i-FunBox 之类的软件也没有替你修改的话)。还有,所有 .sh 结尾的文件都要给 0755 权限。然后,在电脑上 ./connect.sh,会自动调用刚刚拷贝过去的 ovpncon.sh 然后连接上网。Enjoy then!可能会有一些小 Bug,比如 iCloud 无线同步时好时坏(亲测 iOS 5.0.1 工作,iOS 6.1 不工作),或者是推送(亲测 iOS 4.2.1 不工作,iOS 5.0.1 工作,iOS 6.1 工作),又或者是 iMessage(亲测 iOS 5.0.1 不工作,iOS 6.1 工作)。
没有评论:
发表评论