Yonsm.NET 2017-03-15T07:28:22+00:00 Yonsm@msn.com BestVideo - ffmpeg 转码脚本 for macOS & Windows 2017-03-10T10:46:31+00:00 Yonsm http://yonsm.net/bestvideo ffmpeg 是全能的多媒体文件转码工具,也是很多 GUI 类转码软件的后端,但实际用下来这些 GUI 转码软件经常达不到各种定制化的要求,最终还是人肉敲命令行用的靠谱。但是每次敲命令行,各种参数记不住、复杂、累。做成批量的脚本,用起来比较舒服,还可方便普通用户,一键双击批量转码。在此基础上,还能基于 macOS bash shell 和 Windows batch 脚本,做到了简单的 srt/ass 脚本编码检测并混合硬字幕功能,不妨一看:

功能:

  1. 批量处理指定目录、当前目录、脚本目录下的 mp4 mkv mov avi wmv vob 文件(其它扩展名自行编辑添加);
  2. 处理指定文件名;
  3. 混合同文件名名 srt/ass 字幕(自动检测 UTF 编码,默认 GB18030 编码);

使用步骤:

  1. 下载附件,解压缩;
  2. (可选)修改 BestVideo.cmd 或 BestVide.sh 中的相关参数(主要是目标宽度和高度,以及其它更进一步的定制化参数修改)。
  3. 把要转码的文件放在通 BestVideo.cmd 或 BestVide.sh 同一个目录;
  4. (可选)如果需要硬编码字幕,确保 srt 和 ass 字幕文件和视频文件同名;
  5. 双击 BestVideo.cmd (Windows)或 BestVide.sh (macOS,之前需确保 chmod +x BestVideo.sh 过),等待转码完成;
  6. 在 OUT 目录下可以找到同名视频文件。

下载

下载 macOS 版

下载 Windows 版

脚本

macOS 版(在10.12.3测试通过)

#!/bin/sh

inTypes="mp4|mkv|mov|avi|wmv|vob"
outDir=OUT

videoWidth=720
videoHeight=338
videoLevel=3.1
videoProfile=main
videoConstantRateFactor=17

audioChannel=2
audioCodec=aac
audioBitRate=225k
audioSampleRate=44.1k

audioOptions="-acodec $audioCodec -ab $audioBitRate -ar $audioSampleRate -ac $audioChannel"
videoOptions="-s ${videoWidth}x$videoHeight -vcodec libx264 -crf $videoConstantRateFactor -profile:v $videoProfile -level $videoLevel"
cropOptions1="-vf crop=in_w:in_w*$videoHeight/$videoWidth"
cropOptions2="-vf crop=in_h*$videoWidth/$videoHeight:in_h"

CDIR=$(cd "${0%/*}"; pwd)
PATH=$CDIR:$PATH
pushd $PWD >/dev/null

if [ $# = 0 ]; then
	videoPath=.
else
	videoPath="$1"
fi

MakeVideo()
{
	if [ ! -d "$outDir" ]; then mkdir "$outDir"; fi

	subtitle="${1%.*}.ass"
	if [ ! -f "$subtitle" ]; then subtitle="${1%.*}.srt"; fi
	if [ -f "$subtitle" ]; then 
		detectedCharset=`file -b --mime-encoding "$subtitle"`
		if [[ "$detectedCharset" =~ "utf" ]]; then charsetOption=; else charsetOption=":charenc=GB18030"; fi
		echo "Subtitle: $subtitle"
		echo "Charset: $detectedCharset"
		ffmpeg -i "$1" -y $audioOptions $videoOptions $cropOptions1,subtitles="$subtitle"$charsetOption "$outDir/${1%.*}.mp4" </dev/null
		if [ $? == 1 ]; then
			ffmpeg -i "$1" -y $audioOptions $videoOptions $cropOptions2,subtitles="$subtitle"$charsetOption "$outDir/${1%.*}.mp4" </dev/null
		fi
	else
		ffmpeg -i "$1" -y $audioOptions $videoOptions $cropOptions1 "$outDir/${1%.*}.mp4" </dev/null
		if [ $? == 1 ]; then
			ffmpeg -i "$1" -y $audioOptions $videoOptions $cropOptions2 "$outDir/${1%.*}.mp4" </dev/null
		fi
	fi
}

if [ -d "$videoPath" ]; then
	cd "$videoPath"
	find -E . -iregex ".*\.($inTypes)" -maxdepth 1 | while read f ; do MakeVideo "${f##*/}" ; done
	if [ ! -d "$outDir" ]; then
		cd "$CDIR"
		find -E . -iregex ".*\.($inTypes)" -maxdepth 1 | while read f ; do MakeVideo "${f##*/}" ; done
		if [ ! -d "$outDir" ]; then
			echo "Usage: $0 [FILE|DIR|] - Empty means ./ or $CDIR"
		fi
	fi
else
	if [[ "${videoPath}" =~ "/" ]]; then cd "${videoPath%/*}"; fi
	MakeVideo "${videoPath##*/}"
fi

popd >/dev/null

Windows 版(在 Windows 7 下测试通过)

@ECHO OFF

SET inTypes=*.mp4 *.mkv *.mov *.avi *.wmv *.vob
SET outDir=OUT

SET videoWidth=720
SET videoHeight=338
SET videoLevel=3.1
SET videoProfile=main
SET videoConstantRateFactor=17

SET audioChannel=2
SET audioCodec=aac
SET audioBitRate=225k
SET audioSampleRate=44.1k

SET audioOptions=-acodec %audioCodec% -ab %audioBitRate% -ar %audioSampleRate% -ac %audioChannel%
SET videoOptions=-s %videoWidth%x%videoHeight% -vcodec libx264 -crf %videoConstantRateFactor% -profile:v %videoProfile% -level %videoLevel%
SET cropOptions1=-vf crop=in_w:in_w*%videoHeight%/%videoWidth%
SET cropOptions2=-vf crop=in_h*%videoWidth%/%videoHeight%:in_h

PATH=%PATH%;%~dp0
PUSHD %CD%

IF [%1]==[] (
	SET videoPath=.
) ELSE (
	SET videoPath=%1
)

IF EXIST %videoPath%\NUL (
	CD /d %videoPath%
	FOR %%I IN (%inTypes%) DO CALL :MakeVideo "%%~nxI"
) ELSE (
	CD /d %~dp1
	CALL :MakeVideo "%~nx1"
)

POPD
EXIT /b 0

:MakeVideo
	SET subtitleOptions=
	SET subtitle=%~n1.ass
	IF NOT EXIST "%subtitle%" SET subtitle=%~n1.srt
	IF NOT EXIST "%subtitle%" GOTO :endSubtitle
		SET charsetOption=
		CALL :DetectCharset "%subtitle%"
		IF NOT ERRORLEVEL 1 SET charsetOption=:charenc=GB18030
		SET subtitleOptions=",subtitles=%subtitle%:original_size=%videoWidth%x%videoHeight%%charsetOption%"
		ECHO.
		ECHO Subtitle: %subtitle%
		ECHO Charset: %detectedCharset%
	:endSubtitle

	IF NOT EXIST %outDir% MD %outDir%
	@ECHO ON
	ffmpeg -i %1 -y %audioOptions% %videoOptions% %cropOptions1%%subtitleOptions% "%outDir%\%~n1.mp4"
	IF %ERRORLEVEL% EQU 1 ffmpeg -i %1 -y %audioOptions% %videoOptions% %cropOptions2%%subtitleOptions% "%outDir%\%~n1.mp4"
	@ECHO OFF
EXIT /b 0

:DetectCharset
	SET hexFile=%~n1.hex
	CERTUTIL -f -encodehex %1 "%hexFile%" >NUL
	FOR /f "usebackq delims=" %%E IN ("%hexFile%") DO (
		SET "firstLine=%%E" >NUL
		GOTO :endFor
	)
	:endFor
	DEL /Q /F "%hexFile%" >NUL 2>&1

	ECHO %firstLine% | FIND "ef bb bf"     >NUL && SET "detectedCharset=UTF-8"     && EXIT /b 1
	ECHO %firstLine% | FIND "ff fe 00 00"  >NUL && SET "detectedCharset=UTF-32 LE" && EXIT /b 5
	ECHO %firstLine% | FIND "ff fe"        >NUL && SET "detectedCharset=UTF-16"    && EXIT /b 2
	ECHO %firstLine% | FIND "fe ff 00"     >NUL && SET "detectedCharset=UTF-16 BE" && EXIT /b 3
	ECHO %firstLine% | FIND "00 00 fe ff"  >NUL && SET "detectedCharset=UTF-32 BE" && EXIT /b 4
	SET "detectedCharset=ASCII"
EXIT /b 0

仅记录

]]>
LibAhead for iOS - 在未越狱设备上修改三方APP的功能 2015-01-31T03:46:31+00:00 Yonsm http://yonsm.net/libahead 折腾了两个晚上,已搞定在未越狱 iOS 上向第三方 APP 注入 dylib 模块的方案!

通过这个方案,使“微信去广告显IP删弧宠 for iOS ”成为可能(戏谑,但实现起来确实将比 Win32 下简单容易很多)。目前已实测在微信 iPhone 版中添加代码,强制开启“羊年春晚摇一摇”功能,不仅可以抢先体验提前穿越,还能随意控制原本随机摇出的各种功能(剧透:过年的时候微信摇一摇会有:新春红包、上传全家福到春晚、明信片、明星拜年、播放音乐、“甜蜜时光”、啥也没摇到、春晚节目单等功能:)。

思路和十多年前的 AheadLib for Win32 创意方案一样。决定和 AheadLib 一样,做个自动化生成代码的工具,名字都想好了,LibAhead for iOS。宇宙依然,但青年不再,所以拖拖拉拉是难免的,哈

针对特定 APP 写的 CydiaSubstrate dylib 模块,稍加处理即可集成到第三方 APP 里,并运行于未越狱的设备中。各种系统权限突破之类的还是老实点——干不了的;因为涉及修改 IPA 包,重新签名也是必须的。

后续再把细节和工具慢慢补上……

AppStore 之外(如蒲公英、同步推、快用、PP助手等)下载的 APP 都可能不是安全的——即使是未越狱的手机,基于以上功能完全可以在官方 APP 基础上做各种拦截和功能扩展。

2015.02.06 更新:扯淡了,根本不需要转发,直接修改 Mach-O Load Command 表,插入 dylib 然后重新签名即可搞定一切,自动化工具已完成,未广泛测试:https://github.com/Yonsm/iPAFine

]]>
分析 Substrate 的 THUMB 函数 Hook 实现细节 2014-07-12T00:14:31+00:00 Yonsm http://yonsm.net/armhook ARM 架构的 CPU 有 ARM 和 THUMB 执行态。

####1. 先说 ARM 态(被Hook的函数)到 ARM 态(自己的替换函数)的 HOOK

非常简单,没有看过 Substrate 的时候我就想到并验证过了(8 个字节):

  LDR PC, [PC, #-4]
  replacedFunctionAddress  ; 目标绝对地址(ARM 态的,偶数)

####2. ARM 态到 THUMB 态的 HOOK

和上面应该应该类似,只是 变成 replacedFunctionAddress + 1,转跳后自动切换到 THUMB 态。

  未验证(X!)

####3. THUMB 到 THUMB 态的 HOOK

难理解的来了,经过实际测试发现下面的代码可以 HOOK 任意的函数(包括未导出的私有函数)(注意,hookedFunctionAddress 如果是 THUMB 的,则需要 + 1——MD,在这栽了好长一段时间,感谢曾半仙)

  _MSHookFunction(hookedFunctionAddress + 1, (void *)replacedFunctionAddress, (void **)&pOriginalFunction); 

用以上 Substrate 的方法实现 THUMB 到 THUMB 的 HOOK 之后,我用 GDB 查看了一下内存,总共修改了12个字节,如下:

  (gdb) x/3xw _mh_execute_header+0x1073E0
  0x15e3e0 <_mh_execute_header+1078240>:	0x46c04778	0xe51ff004	0x0029b6b9  

反汇编代码(注意 THUMB 模式的 disas 地址要 +1 变成奇数):

  (gdb) disas _mh_execute_header+0x1073E1 _mh_execute_header+0x1073EC
  Dump of assembler code from 0x15e3e1 to 0x15e3ec:
  0x0015e3e1 <_mh_execute_header+1078241>:	bx	pc
  0x0015e3e3 <_mh_execute_header+1078243>:	nop			(mov r8, r8) 
  0x0015e3e5 <_mh_execute_header+1078245>:	blx	0x562e24 ; 请忽略
  0x0015e3e9 <_mh_execute_header+1078249>:	undefined ; 请忽略
  0x0015e3eb <_mh_execute_header+1078251>:	lsls	r1, r5, #0 ; 请忽略

第一条指令(C0 46)就是 THUMB 的 BX PC,第二条指令是 78 47 是 THUMB 的 NOP。后面的指令因为实际上是 BX 成 ARM 态了,所以请忽略。

BX PC 后实际上是转跳到了 ARM 态的 0x0015e3e4 地址,继续反汇编如下:

  (gdb) disas _mh_execute_header+0x1073E4 _mh_execute_header+0x1073EC
  Dump of assembler code from 0x15e3e4 to 0x15e3ec:
  0x0015e3e4 <_mh_execute_header+1078244>:	ldr	pc, [pc, #-4]	; 0x15e3e8 <_mh_execute_header+1078248>
  0x0015e3e8 <_mh_execute_header+1078248>:	strheq	r11, [r9], -r9 ; 这个就是和 replacedFunctionAddress + 1 了

可以看到从 0x0015e3e4 这里开始和上面提到的第一种情况(从ARM到THUMB)一样了。

补充:感谢 riusksk 做了一个直观图解,非常容易看明白:

####4. 从 THUMB 到 ARM

  你猜~~

####关于转跳

  * 如果操作数类型是imm, 那就是互换状态. ARM下到thumb, thumb下调用就到ARM;
  * 如果操作数是寄存器 根据低位地址,奇数为 THUMB,偶数为 ARM。

知道了上述 HOOK 方法,再构造一个 pOriginalFunction,结合 Inject Dylib 的方法,就可以自己实现 Substrate 的完整功能了。

(上面仅 3 是对 Substate 的 Hook 分析,其它是我 YY 的,不确定 Substrate 也是这样的实现,有兴趣的话可以自己反汇编/反编译 Substrate 去看实现细节)

]]>
Re-Symbolicate iOS Crash Report 2014-06-24T17:31:42+00:00 Yonsm http://yonsm.net/resymbolicate Xcode Organizer 连接手机看 Device Logs 的时候,有个 Re-Symbolicate 功能可以根据地址反查 Call Stack 中系统模块(如UIKit、CoreFoundation等)的符号信息。

如果收到的是第三者设备提供过来的Crash Log,则无法使用该功能。使用以下命令可以实现同样的目的:

  export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash -v ~/CrashLog.crash

上面提到的是反查系统模块的符号,下面这个则是根据崩溃地址和dSYM来反查自己程序模块中的符号:

dwarfdump --lookup 0x00002712 -arch armv7 CrashTesting.app.dSYM/

一旦从地址中反查到了符号,将非常有助于分析Crash的原因。

(2014.11.22 验证)

]]>
GitHub 页面 2014-05-18T23:08:31+00:00 Yonsm http://yonsm.net/github 稍微整理了一下我的 GitHub 页面,部分代码会持续维护。

]]>
Camo - Xcode 反逆向工程分析的混淆方案 2014-02-27T22:08:31+00:00 Yonsm http://yonsm.net/camo 逆向工程分析的三大线索是:字符串、导入表、函数名。我捣鼓了一个自己的方案,以加大 iOS/OSX 程序的逆向分析难度:

  1. Camo 程序中搜索源代码目录,找出所有 Object 类名、方法名、属性名的符号,排除掉xcode iPhone SDK 中的符号(也是自动搜索获取),再排除掉导出的和第三方依赖的符号(都是根据参数自动获取)。然后把这些名称全部#define 一下成为随机的名称,写到一个.h中;

  2. 在 Prefix.pch 的最前面#import这个自动生成的.h。去掉这个.h一样可以编译,加上.h就是混淆名称,没有任何副作用。

PS:Generate Debug Symbol一定要去掉(Xcode默认创建的project,即使是Release[Archive/Profile]编译也启用了Generate Debug Symbol的),去掉之后“等同于源代码”的问题可以有很大的改观。

期望以后Camo还支持一个另外的两个特性:加密所有的字符串,所有的函数调用(全部使用dlsym来动态获取)。这样编译出来的二进制文件几乎自己都认不出来了。

完整的混淆方案,后面再整理 Check List。

2014.07.30 补充:

终于出成品了,参看:https://github.com/Yonsm/Camo

]]>
另类思维实现 Mac OS X 下的 mount bind 2014-02-26T19:50:17+00:00 Yonsm http://yonsm.net/mountbind *nix 下的 mount 基本上都支持 -o bind 来绑定另外一个目录到特定目录中。但 Mac OS X 的 mount 确不支持此功能,有时候这个“特性”非常让人郁闷——比如,百度网盘的脑残设计,强制设定只能同步到一个叫“百度云同步盘”的目录中,ln -s 创建的外部链接目录都不支持(需求场景,SSD小硬盘,某个存放大姐姐们的目录在NAS或移动硬盘上,但是想跟百通网盘同步)。

几经尝试,终于找到一个曲线实现的方法:用 mount_afp 来模拟 mount -o 的功能:

如果是本地移动硬盘,先确保该目录已共享,然后执行

mount_afp afp://user:pass@localhost/Movies ~/百度云同步盘/Movies

搞定了。

后话:我扯淡了,半夜才想起来,以前创建 RAMDISK 的时候用的 mount -t hfs -o union ** ** 就可以实现这种功能……

]]>
在iOS上深度追踪HTTP/UIWebView/openURL/SSL的方法和插件 2014-02-21T22:50:17+00:00 Yonsm http://yonsm.net/httpeek HTTP 请求 Sniffer 很多工具可以做,至于 HTTPS 则使用 Charles 做中间人攻击也可以拿到全部 HTTPS 请求的细节,并且不限定于 iOS(具体方法这里就不说了,不是本文重点)。

但是,这些协议层的分析往往只能分析协议细节,想要深度追踪 HTTP/HTTPS/UIWebView 数据的生成细节的话,很多时候还是无能为力的。此时我们需要定位到数据生成的进程、模块、调用堆栈,进而找到相关代码继续做逆向工程分析——HttPeek 插件就是这样用途的插件,用法:

  1. 在已越狱的系统中安装 Cydia Substrate;

  2. 把 HttPeek.dylib 点此下载 放到 Cydia Substrate 的插件目录中(/Library/MobileSubstrate/DynamicLibraries),并重启设备或相关进程;

  3. 操作重现,确保你期望监听的 HTTP/HTTPS/UIWebView/SSL 请求已发生;

  4. 在 /tmp/%进程名称%.req 目录中获取改进程所有的 HTTP/HTTP/UIWebView/SSL 请求细节的日志,比如:

     FROM /System/Library/PrivateFrameworks/iTunesStore.framework/iTunesStore(0x3990e000)-<redacted>(0x399183e1=>0x0093e1)
     <(
         0   HttPeek.dylib                       0x0199fcb1 _Z10LogRequestP12NSURLRequestPv + 496
         1   HttPeek.dylib                       0x019a03cb _Z22$NSURLConnection_startP11objc_objectP13objc_selector + 50
         2   iTunesStore                         0x3991880b <redacted> + 1066
         3   iTunesStore                         0x399183a5 <redacted> + 360
         4   iTunesStore                         0x399148df <redacted> + 386
         5   iTunesStore                         0x3991f78b <redacted> + 598
         6   iTunesStore                         0x3991e421 <redacted> + 544
         7   iTunesStore                         0x399137cd <redacted> + 288
         8   iTunesStore                         0x39912c69 <redacted> + 620
         9   iTunesStore                         0x3991230d <redacted> + 276
         10  iTunesStoreUI                       0x39a636bb <redacted> + 354
         11  iTunesStoreUI                       0x39a63011 <redacted> + 164
         12  iTunesStore                         0x399137cd <redacted> + 288
         13  iTunesStore                         0x39912c69 <redacted> + 620
         14  Foundation                          0x315c07db <redacted> + 770
         15  Foundation                          0x31664995 <redacted> + 60
         16  libdispatch.dylib                   0x3b5bb68f <redacted> + 110
         17  libdispatch.dylib                   0x3b5bcd71 <redacted> + 220
         18  libdispatch.dylib                   0x3b5bcf59 <redacted> + 56
         19  libsystem_pthread.dylib             0x3b6f7dbf _pthread_wqthread + 298
         20  libsystem_pthread.dylib             0x3b6f7c84 start_wqthread + 8
     )>
     POST: https://play.itunes.apple.com/WebObjects/MZPlay.woa/wa/signSapSetup
     {
         "Accept-Language" = "zh-Hans";
         Cookie = "mzf_odc=ST1; xp_ci=3z22aB6Jz841z576zB2szwxWTgkNv; mzf_in=112351; s_vi=[CS]v1|2983AD4B05010B41-600001338012E27D[CE]; Pod=11; itspod=11; ns-mzf-inst=36-85-80-109-88-8294-112351-11-st11; session-store-id=d79638dc54b6dec6c1116ba8fe8e4d84";
         "User-Agent" = "AppStore/2.0 iOS/7.0.4 model/iPhone4,1 (6; dt:73)";
         "X-Apple-Client-Versions" = "GameCenter/2.0";
         "X-Apple-Connection-Type" = WiFi;
         "X-Apple-Partner" = "origin.0";
         "X-Apple-Store-Front" = "143465-19,21 t:native";
     }
    
     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0">
     <dict>
         <key>sign-sap-setup-buffer</key>
         <data>
         AgAAANIISnQ/0ZM7Y5AO05eY5ugZbrkHNJoRsyFGn+P03FNKZTQmjN/Ha0pbt9Xkfgjz
         rrdfL3kxiThvq7duDjJp3GO7OatGg7Iyr7x/RJtClXmAoK2uL0rjxqyN36cgIbmYrP2I
         ZidsvuCHDj13S77kleOuKkuGFZN3JxIMm0OfJG7sqL/GO+2Upo8k0adRhiMj9asFhCxI
         LdxM2hcZ30cXKhV+fCRYybJm4UHX33lHAWed+6rty6gMzK+m/QbUWhTR2XCWOrEFs+qM
         Xq1QULQ3kJGPlVYFHaFoVDXRzfsNLTCsql353InFNdTxMdNTxqt9YqmmT+apJTHUq8xA
         +C9FOQ6G/u35sTGOZUUPxtjTiauYdfYgBs5ULIjwCQAAADCsp7cq8VDLhfHkRGX0idYF
         kNxP/T1GaG1V0U9kWE0gT5cFAPe464nMsRgxouM2wwEf4hsJkobd98rw1a4xrOAEtFn1
         iw==
         </data>
     </dict>
     </plist>
    

可以看到,Charles 等常规 Sniffer 软件中能看到的发送和接收细节都有,此外还有完整的 CallStack 记录,上例中一看就知道数据是 /System/Library/PrivateFrameworks/iTunesStore.framework/iTunesStore 这个模块发送的的请求,在 Xcode 的 iOS SDK 中可以找到这个模块,进而继续逆向分析它。

PS1:HttPeek 还支持 UIWebView Request、UIAplicaiton openURL、SSLRead/SSLWrite、CFReadStreamCreateForHTTPRequest 的监听,同时还支持SSL 认证禁用(以便使用中间人代理来分析 SSL 网络交互)。

PS2:源代码可获取:https://github.com/Yonsm/HttPeek

]]>
[转载]用C++进行设计模式的解析和实现 2014-02-12T20:30:17+00:00 Yonsm http://yonsm.net/designpattern 用C++设计模式的解析和实现

]]>
使用 WPAD 配合 GAE 实现客户端准零配置科学上网 2014-01-28T20:30:17+00:00 Yonsm http://yonsm.net/wpad WPAD 是 Web Proxy Auto Discovery 的缩写,可以看做是是 PAC 的扩展应用。

简单说来,以前在浏览器中指定 PAC 文件或者地址,WPAD 就是在 DHCP 的时候自动发现 PAC(实际上也可以在 DNS 中发现 PAC,不过推荐 DHCP 中发现)。

直接说步骤:

  1. 首先假定您已经在局域网内配置好 GAE Proxy,且启用了 PAC 文件,这里假设 PAC 是 http://192.168.1.1:8086/proxy.pac

  2. 在 DNSMasQ 中配置 WPAD,加入一行:dhcp-option=252,http://192.168.1.1:8086/proxy.pac

    服务端 WPAD 配置完毕,简单吧。

  3. 客户端,请确保客户端是 DHCP 获取 IP 地址的。

    Mac OS X:设置 -> 网络 -> 选定网络(比如以太网或者 Wi-Fi)-> 高级 -> 代理 -> 自动发现代理 -> 勾上

    Windows:Internet Explorer 属性 -> 连接 -> 自动检测设置(此设置可能已经默认开启,也就是说 Windows 系统零配置)

    万事搞定,之后畅享零配置科学上网吧。

这样好的好处是不言而喻的,服务端配置好后,客户端(Windows、Mac OS X 均可,其它客户端应该也行)只要勾选一个选项,无需做其它额外配置,DHCP 的时候将自动发现,可以实现科学上网。且切换 到别的网络后,自动就使用别的网络的代理设置了(或者该网络没有配置代理,则自动直连了)。

这是我现在为止尝试到的最简单(准零配置)、最方便(支持HTTPS)、最廉价(GAE 免费使用)的方案,什么 VPN、S**Sock、套神马的,不是要钱就是不稳定,也不能长期使用。

]]>