-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop', version 0.9.2
- Loading branch information
Showing
19 changed files
with
574 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
language: go | ||
go: | ||
- 1.1 | ||
- 1.3 | ||
env: | ||
- TRAVIS="yes" | ||
install: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# COW (Climb Over the Wall) proxy | ||
|
||
COW is a HTTP proxy to simplify bypassing the great firewall. It tries to automatically identify blocked websites and only use parent proxy for those sites. | ||
|
||
Current version: 0.9.1 [CHANGELOG](CHANGELOG) | ||
[![Build Status](https://travis-ci.org/cyfdecyf/cow.png?branch=develop)](https://travis-ci.org/cyfdecyf/cow) | ||
|
||
## Features | ||
|
||
- As a HTTP proxy, can be used by mobile devices | ||
- Supports HTTP, SOCKS5, [shadowsocks](https://github.com/clowwindy/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E) and COW itself as parent proxy | ||
- Supports simple load balancing between multiple parent proxies | ||
- Automatically identify blocked websites, only use parent proxy for those sites | ||
- Generate and serve PAC file for browser to bypass COW for best performance | ||
- Contain domains that can be directly accessed (recorded accoring to your visit history) | ||
|
||
# Quickstart | ||
|
||
Install: | ||
|
||
- **OS X, Linux (x86, ARM):** Run the following command (also for update) | ||
|
||
curl -L git.io/cow | bash | ||
|
||
- **Windows:** [download](http://dl.chenyufei.info/cow/) | ||
- If you are familiar with Go, run `go get github.com/cyfdecyf/cow` to install from source. | ||
|
||
Modify configuration file `~/.cow/rc` (Linux) or `rc.txt` (Windows). A simple example: | ||
|
||
Here's an example with the most important options: | ||
|
||
# Line starting with # is comment and will be ignored | ||
# Local proxy listen address | ||
listen = http://127.0.0.1:7777 | ||
|
||
# SOCKS5 parent proxy | ||
proxy = socks5://127.0.0.1:1080 | ||
# HTTP parent proxy | ||
proxy = http://127.0.0.1:8080 | ||
proxy = http://user:[email protected]:8080 | ||
# shadowsocks parent proxy | ||
proxy = ss://aes-128-cfb:[email protected]:8388 | ||
# cow parent proxy | ||
proxy = cow://aes-128-cfb:[email protected]:8388 | ||
|
||
The PAC file can be accessed at `http://<listen>/pac`, for the above example: `http://127.0.0.1:7777/pac`. | ||
|
||
Command line options can override options in the configuration file For more details, see the output of `cow -h` | ||
|
||
## Blocked and directly accessible sites list | ||
|
||
In ideal situation, you don't need to specify which sites are blocked and which are not, but COW hasen't reached that goal. So you may need to manually specify this if COW made the wrong judgement. | ||
|
||
- `~/.cow/blocked` for blocked sites | ||
- `~/.cow/direct` for blocked sites | ||
- One line for each domain | ||
- `google.com` means `*.google.com` | ||
- You can use domains like `google.com.hk` | ||
|
||
# Technical details | ||
|
||
## Visited site recording | ||
|
||
COW records all visited hosts and visit count in `~/.cow/stat`, which is a json file. | ||
|
||
- **For unknown site, first try direct access, use parent proxy upon failure. After 2 minutes, try direct access again** | ||
- Builtin [common blocked site](site_blocked.go) in order to reduce time to discover blockage and the use parent proxy | ||
- Hosts will be put into PAC after a few times of successful direct visit | ||
- Hosts will use parent proxy if direct access failed for a few times | ||
- To avoid mistakes, will try direct access with some probability | ||
- Host will be deleted if not visited for a few days | ||
- Hosts under builtin/manually specified blocked and direct domains will not appear in `stat` | ||
|
||
## How does COW detect blocked sites | ||
|
||
Upon the following error, one domain is considered to be blocked | ||
|
||
- Server connection reset | ||
- Connection to server timeout | ||
- Read from server timeout | ||
|
||
COW will retry HTTP request upon these errors, But if there's some data sent back to the client, connection with the client will be dropped to signal error.. | ||
|
||
Server connection reset is usually reliable in detecting blocked sites. But timeout is not. COW tries to estimate timeout value every 30 seconds, in order to avoid considering normal sites as blocked when network condition is bad. Revert to direct access after two minutes upon first blockage is also to avoid mistakes. | ||
|
||
If automatica timeout retry causes problem for you, try to change `readTimeout` and `dialTimeout` in configuration. | ||
|
||
# Limitations | ||
|
||
- No caching, COW just passes traffic between clients and web servers | ||
- For web browsing, browsers have their own cache | ||
- Blocked site detection is not always reliable | ||
|
||
# Acknowledgements | ||
|
||
Refer to [README.md](README.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,15 +53,17 @@ func TestTunnelAllowedPort(t *testing.T) { | |
} | ||
|
||
func TestParseProxy(t *testing.T) { | ||
parentProxy = nil | ||
var ok bool | ||
pool, ok := parentProxy.(*backupParentPool) | ||
if !ok { | ||
t.Fatal("parentPool by default should be backup pool") | ||
} | ||
cnt := -1 | ||
|
||
var parser configParser | ||
parser.ParseProxy("http://127.0.0.1:8080") | ||
cnt++ | ||
|
||
hp, ok := parentProxy[cnt].proxyConnector.(*httpParent) | ||
hp, ok := pool.parent[cnt].ParentProxy.(*httpParent) | ||
if !ok { | ||
t.Fatal("1st http proxy parsed not as httpParent") | ||
} | ||
|
@@ -71,7 +73,7 @@ func TestParseProxy(t *testing.T) { | |
|
||
parser.ParseProxy("http://user:[email protected]:9090") | ||
cnt++ | ||
hp, ok = parentProxy[cnt].proxyConnector.(*httpParent) | ||
hp, ok = pool.parent[cnt].ParentProxy.(*httpParent) | ||
if !ok { | ||
t.Fatal("2nd http proxy parsed not as httpParent") | ||
} | ||
|
@@ -84,7 +86,7 @@ func TestParseProxy(t *testing.T) { | |
|
||
parser.ParseProxy("socks5://127.0.0.1:1080") | ||
cnt++ | ||
sp, ok := parentProxy[cnt].proxyConnector.(*socksParent) | ||
sp, ok := pool.parent[cnt].ParentProxy.(*socksParent) | ||
if !ok { | ||
t.Fatal("socks proxy parsed not as socksParent") | ||
} | ||
|
@@ -94,7 +96,7 @@ func TestParseProxy(t *testing.T) { | |
|
||
parser.ParseProxy("ss://aes-256-cfb:[email protected]:1080") | ||
cnt++ | ||
_, ok = parentProxy[cnt].proxyConnector.(*shadowsocksParent) | ||
_, ok = pool.parent[cnt].ParentProxy.(*shadowsocksParent) | ||
if !ok { | ||
t.Fatal("shadowsocks proxy parsed not as shadowsocksParent") | ||
} | ||
|
Oops, something went wrong.