The old bbs
can be found here
bbs
is a router for SOCKS and HTTP proxies. It exposes SOCKS5 or HTTP
CONNECT services and forwards incoming requests to proxies or chains of proxies
based on the request's target. Routing can be configured with a PAC script (if
built with PAC support), or through a JSON file.
go install github.com/synacktiv/bbs@master
To install bbs with PAC script support:
go install -tags pac github.com/synacktiv/bbs@master
Note: PAC relies on unaudited third-party libraries.
Configuration is performed in one JSON file composed of multiple sections:
- Proxies: defines all the upstream proxies used by bbs
- Chains: defines the differents chains of previously defined proxies, and their settings
- Routes: defines the different routing tables
- Servers: defines the listeners (SOCKS5 or HTTP) opened by bbs
- Hosts: defines custom hosts resolution (in a /etc/hosts way)
The configuration file path is provided through argument -c <path>
(default to ./bbs.json
).
bbs
reloads configuration files on SIGHUP, use kill -HUP <pid>
to reload.
Here is an example of such configuration:
{
"proxies": {
"proxy1": {
"connstring": "socks5://127.0.0.1:1337",
"user": "user",
"pass": "s3cr3t"
},
"proxy2": {
"connstring": "http://127.0.0.1:1338"
}
},
"chains": {
"chain1": {
"proxyDns": true,
"tcpConnectTimeout": 1000,
"tcpReadTimeout": 2000,
"proxies": [
"proxy1",
"proxy2"
]
},
"direct": {
"proxies": []
}
},
"routes": {
"table1": [
{
"comment": "Block1 comment",
"rules": {
"rule": "regexp",
"variable": "host",
"content": "me\\.gandi\\.net"
},
"route": "chain1"
},
{
"comment": "Route web traffic towards 10.35.0.0/16 through chain1",
"rules": {
"rule1": {
"rule": "subnet",
"content": "10.35.0.0/16"
},
"op": "AND",
"rule2": {
"rule": "regexp",
"variable": "port",
"content": "^(80|443)$"
}
},
"route": "chain1"
},
{
"comment": "Drop traffic to 445",
"rules": {
"rule": "regexp",
"variable": "port",
"content": "^445$"
},
"route": "drop"
},
{
"comment": "Route *.corp.local through chain2",
"rules": {
"rule": "regexp",
"variable": "host",
"content": "(?i)^(.*\\.)?corp\\.local$"
},
"route": "chain1"
},
{
"comment": "Default routing through direct chain",
"rules": {
"rule": "true"
},
"route": "direct"
}
],
"table2": [
{
"comment": "Default routing through chain1",
"rules": {
"rule": "true"
},
"route": "chain1"
}
]
},
"servers": [
"socks5://127.0.0.1:1081:table1",
"http://127.0.0.1:1080:table2"
],
"hosts": {
"host1": "1.1.1.1",
"host2": "10.0.0.1"
}
}
Upstream proxies must be declared in the proxies
section as a map of proxy
structures. Map keys are chosen freely but must match the ones used in chains
definition. Proxy structures are like this:
connstring
is required with formatprotocol://host:port
(protocol
can besocks5
orhttpconnect
/http
)user
andpass
are optional
Chains must be declared in the chains
section as a map of chain structures.
Map keys are chosen freely by must match with the ones used in routes definition.
Chain structures have proxychains-like parameters (cf. https://github.com/rofl0r/proxychains-ng):
proxyDns
: boolean, optional, defaults totrue
tcpConnectTimeout
: integer, optional, defaults to 1000tcpReadTimeout
: integer, optional, defaults to 2000proxies
: string list, optional, defaults to empty list
The proxies
key of a chain
must contain an array of proxy names declared as keys in the proxies
section.
The built-in configuration mode for routing is through the configuration file. It associates
addresses with chain names. The file must contain a map of routing tables. Map keys
are chosen freely but must match the ones used in the servers
section.
Each routing table is an array of rule blocks. Each
rule block contains a comment
, a set of rules
, and an associated chain
name. Rules are evaluated: given an address in the host:port
format, they can
be true
or false
. For a given address, blocks are evaluated in their
declaration order. The evaluation stops at the first block that is true
and
the associated chain name is returned. Each opened server (from servers
section)
is associated with one routing table from the configuration. Requests received on
each server are routed according to the matching routing table.
Block fields:
comment
(string)rules
(Rule or RuleCombo)route
(string)
Rule fields:
rule
(string): rule type,regexp
,subnet
ortrue
.variable
(string): variable for regexp evaluation,host
,port
oraddr
(host:port).content
(string): content of the rule, depends on the rule type (see below).negate
(bool) [optional]: whether to negate the rule.
RuleCombo fields:
rule1
(Rule or RuleCombo): left operand.op
(string): operator,AND
,And
,and
,&
,&&
,OR
,Or
,or
,|
,||
.rule2
(Rule or RuleCombo): right operand.
Rule types:
regexp
: match the variable defined invariable
(host
,port
oraddr=host:port
) against the regexp incontent
.subnet
: checks if host is in the subnet defined incontent
. If host is a domain name and not a subnet address, the rule returns false.true
: returnstrue
for every address. Useful for default routing at the end of the block array.
The rule blocks from routes
section or the PAC function must return declared
chain names, not proxy names. If you want to use a single proxy, you must wrap
it in a chain. The drop
name is special and does not need to be declared in
this configuration. If the PAC function or a routing block returns drop
as a
chain name, then the connection is dropped.
If bbs is built with PAC support and -pac
arguments points to a PAC file, routes
defined in the configuration file will not be used. PAC file routing does not support
multiple routing tables. The same PAC file will be used for every opened server.
The listeners opened by bbs must be declared in the servers
section as a list of
connection strings of format protocol://bind_addr:bind_port:routing_table
.
protocol
can behttp
orsocks5
routing_table
must match one of the tables defined inroutes
section
Custom host resolution (similar to /etc/hosts
) can be configured in the
hosts
section as a map of strings. Map keys correspond to the hostname
and the values to the IP address the host should resolve to.
If bbs
is built with PAC support, routing can be configured with a PAC script
instead of a JSON configuration file. However, this requires using an untrusted
Go library. The PAC file path must be provided with -pac
.
The PAC script must define the FindProxyForURL(url, host)
function. The
values returned by this function must match the names of the chains (not the
proxies) declared in the JSON configuration.