Commit 2b2d585c authored by 神楽坂玲奈's avatar 神楽坂玲奈

it works

parent 931c8d6b
pg = require 'pg'
module.exports =
init: (server_id, database)->
init: (server_id, database, callback)->
pg.connect database, (error, client, done) ->
throw error if error
client.query 'SELECT * from servers', (error, result) ->
client.query 'SELECT *, host(address) as host, network(address) as network FROM servers', (error, result) ->
throw error if error
servers = {}
for row in result.rows
row.private_address ?= row.public_address
row.tos = '0x' + row.tos.toString(16) if row.tos?
servers[row.id] = row
client.query 'SELECT * from links where from = $1::int or to = $1::int', [server_id], (error, result) ->
client.query 'SELECT * FROM links WHERE "from" = $1::smallint or "to" = $1::smallint', [server_id], (error, result) ->
throw error if error
for row in result.rows
# row.mode = row.mode.split('-')
# if row.mode.length > 1
# row.mode =
# mode: row.mode[0]
# encap: row.mode[1]
# sport: row.mode[2]
# dport: row.mode[3]
# else
# row.mode =
# mode: row.mode[0]
if row.from == server_id
servers[row.to].link = row
servers[row.to].link = row.mode
servers[row.to].next_hop = row.to
else
servers[row.from].link = row
servers[row.from].link = row.mode
servers[row.from].next_hop = row.from
client.query 'SELECT id FROM regions', (error, result) ->
throw error if error
regions = {}
for row in result.rows
regions[row.id] = addresses: []
regions[row.id] = id: row.id, addresses: []
client.query 'SELECT region_id, address FROM addresses', (error, result) ->
throw error if error
for row in result.rows
regions[row.region_id].addresses.push row.address
reachable_servers = (server.id for server in servers when server.link?)
reachable_servers = (server.id for i, server of servers when server.link?)
reachable_servers.push server_id
client.query 'SELECT DISTINCT ON (region_id) region_id, server_id FROM gateways WHERE server_id in $1 ORDER BY delay', [reachable_servers], (error, result) ->
client.query 'SELECT DISTINCT ON (region_id) region_id, server_id FROM gateways WHERE server_id = ANY($1::smallint[]) ORDER BY region_id, delay', [reachable_servers], (error, result) ->
throw error if error
for row in result.rows
regions[row.region_id].gateway = row.server_id
done()
callback servers, regions
\ No newline at end of file
servers[21].next_hop = 20
servers[22].next_hop = 20
servers[23].next_hop = 20
regions[0].gateway = 21
regions[1].gateway = 23
done()
callback servers, regions
\ No newline at end of file
*nat
-A PREROUTING -p tcp -m set --match-set block_ip src -j REDIRECT --to-ports 3101
-A PREROUTING -i ${RAILGUN_INTERFACE} -p tcp -m addrtype --dst-type LOCAL -m multiport --dports 22,443,3000,1723,5001,5201 -j ACCEPT
-A PREROUTING -i ${RAILGUN_INTERFACE} -p tcp -m addrtype --dst-type LOCAL -m set --match-set ports1 dst -j REDIRECT --to-ports 3128
-A PREROUTING -i ${RAILGUN_INTERFACE} -p tcp -m addrtype --dst-type LOCAL -m set --match-set ports2 dst -j REDIRECT --to-ports 3129
-A PREROUTING -i ${RAILGUN_INTERFACE} -p tcp -m addrtype --dst-type LOCAL -m set --match-set ports3 dst -j REDIRECT --to-ports 1080
-A PREROUTING -i ${RAILGUN_INTERFACE} -p tcp -m addrtype --dst-type LOCAL -j REDIRECT --to-ports 3100
-A OUTPUT -o ${RAILGUN_INTERFACE} -p udp --dport 53 -m owner --uid-owner proxy -j REDIRECT --to-ports 53 # socks5 dns hack
-A POSTROUTING -o ${RAILGUN_INTERFACE} -s 10.0.0.0/8 -j SNAT --to-source ${RAILGUN_PRIVATE_ADDRESS}
COMMIT
*mangle
-A PREROUTING -s ${RAILGUN_ADDRESS}/16 -p tcp -j TPROXY --on-port 5000 --on-ip 0.0.0.0 --tproxy-mark 0x01/0xffffffff
-A PREROUTING -s ${RAILGUN_ADDRESS}/16 ! -p tcp ! -d 10.0.0.0/8 -j TOS --set-tos 4
-A INPUT -s 10.${RAILGUN_ID}.32.0/20,10.${RAILGUN_ID}.64.0/20,10.${RAILGUN_ID}.176.0/20 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
-A OUTPUT -d 10.${RAILGUN_ID}.32.0/20,10.${RAILGUN_ID}.64.0/20,10.${RAILGUN_ID}.176.0/20 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
-A POSTROUTING -o ${RAILGUN_INTERFACE} -j TOS --set-tos 0x3c
COMMIT
db = require './db.coffee'
db = require './db'
protocol = require './protocol'
route = require './route'
server_id = parseInt process.env.RAILGUN_ID
db.init server_id, process.env.RAILGUN_DATABASE, (servers, regions)->
console.log servers, regions
#route.init server_id, servers, regions, ->
# protocol.init server_id, servers, regions, route.update
console.log "loaded #{Object.keys(servers).length} servers and #{Object.keys(regions).length} regions"
route.init server_id, servers, regions, ->
protocol.init server_id, servers, regions, route.update
child_process = require 'child_process'
ip_exec = (commands, force=false, callback)->
args = ['-batch', '-']
if force
args.push '-force'
child = child_process.spawn 'ip', args, stdio: ['pipe', process.stdout, process.stderr]
child.on 'close', callback
child.stdin.end commands.join('\n') + "\n"
iptables_exec = (commands, noflush = false, callback )->
args = []
if noflush
args.push '--noflush'
child = child_process.execFile 'iptables-restore', args, stdio: ['pipe', process.stdout, process.stderr]
result = (["*#{table}"].concat(rules, 'COMMIT').join("\n") for table, rules of commands when rules.length > 0).join("\n") + "\n"
child.on 'close', callback
child.stdin.end result
module.exports =
init: (server_id, servers, regions)->
ip = []
ipforce = []
iptables = {nat: [], mangle: [], filter: []}
ipforce.push "rule del pref 200 fwmark 0x1 lookup 200"
ipforce.push "rule del pref 400 to #{servers[server_id].network} lookup main"
ipforce.push "rule del pref 401 tos 4 lookup 100"
ipforce.push "rule del pref 402 iif lo lookup main"
ipforce.push "rule del pref 403 to 10.0.0.0/8 lookup 100"
ip.push "rule add pref 200 fwmark 0x1 lookup 200"
ip.push "rule add pref 400 to #{servers[server_id].network} lookup main" # 到自己 VPN 内网, 不进行路由
ip.push "rule add pref 401 tos 4 lookup 100" # 源站选路
ip.push "rule add pref 402 iif lo lookup main" # 除源站选路外, 本机发出的其他报文, 不进行路由
ip.push "rule add pref 403 to 10.0.0.0/8 lookup 100" # 转发报文
ip.push "route replace local default dev lo table 200"
ip.push "route flush table 100"
#console.log servers
for i, server of servers when server.id != server_id
# 相邻的节点建立 tunnel
if server.link? and server.link != 'direct'
ipforce.push "link del railgun#{server.id}"
# mode = null
# encap = null
# sport = null
# dport = null
[mode, encap, sport, dport] = server.link.split '-'
if encap
if encap == 'gue'
ipproto='gue'
else if mode == 'ipip'
ipproto='ipproto 4'
else if mode == 'gre'
ipproto='ipproto 47'
ipforce.push "fou del port #{dport}"
ipforce.push "fou add port #{dport} #{ipproto}"
ip.push "link add railgun#{server.id} type #{mode} remote #{server.public_address} ttl 64 encap #{encap} encap-sport #{sport} encap-dport #{dport}"
else
ip.push "link add railgun#{server.id} type #{mode} remote #{server.public_address} ttl 64"
ip.push "addr add dev railgun#{server.id} #{process.env.RAILGUN_ADDRESS} peer #{server.address}"
ip.push "link set dev railgun#{server.id} up"
else if server.next_hop?
# 为了调试方便, 把不相邻但是可达的节点在 main 做个路由, 这个生产不会使用.
ip.push "route replace #{server.network} dev railgun#{server.next_hop} src #{servers[server_id].host}"
# 可达节点的路由
if server.next_hop?
ip.push "route replace #{server.network} dev railgun#{server.next_hop} src #{servers[server_id].host} table 100"
ip.push "route replace tos #{server.tos} default dev railgun#{server.next_hop} src #{servers[server_id].host}" if server.tos?
# 连接保持
if server.tos?
iptables.mangle.push "-A FORWARD -m connmark --mark 0 -m realm --realm #{server.id} -j CONNMARK --set-mark #{server.id}"
iptables.mangle.push "-A FORWARD -m connmark --mark #{server.id} -j TOS --set-tos #{server.tos}"
iptables.mangle.push "-A OUTPUT -m connmark --mark 0 -m realm --realm #{server.id} -j CONNMARK --set-mark #{server.id}"
iptables.mangle.push "-A OUTPUT -m connmark --mark #{server.id} -j TOS --set-tos #{server.tos}"
for i, region of regions when region.gateway?
for address in region.addresses
if region.gateway == server_id
ip.push "route add #{address} via #{process.env.RAILGUN_GATEWAY} table 100"
else
ip.push "route add #{address} advmss 1360 dev railgun#{servers[region.gateway].next_hop} src #{servers[server_id].host} realm #{region.gateway} table 100"
#console.log ipforce.join("\n")
#console.log '-'
ip_exec ipforce, true, (code)->
console.log code
#console.log error, stdout, stderr
#console.log ip.join("\n")
ip_exec ip, false, (code)->
#throw error if error
console.log code
iptables_exec iptables, true, (code)->
console.log code
#throw error if error
process.exit()
#!/usr/bin/env bash
set -o errexit
echo 'ipset...'
ipset create -exist ports1 bitmap:port range 10000-32767
ipset create -exist ports2 bitmap:port range 10000-32767
ipset create -exist ports3 bitmap:port range 10000-32767
ipset create -exist block_ip hash:ip
ipset restore -file ipset
echo 'iptables...'
envsubst < iptables-rules | iptables-restore
echo 'network...'
coffee main.coffee
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment