freebitcoins работает на Google App Engine. Ну, часть, которую вы видите, работает на App Engine.
Там также фоновый bitcoind сервер, работающий на DEBiAN VPS, что я имел в течение многих лет. Код двигателя App делает вызовы JSON-RPC через App Engine URL Fetching API. Изготовление, что соединение безопасно было немного сложно; вот как я это сделал:
Во-первых, я подключиться к VPS с использованием протокола HTTPS, так что трафик шифруется.
Мне нужно безопасное соединение, потому что я добавить секретное предварительно общее значение для вызова JSON. Я не собираюсь, чтобы сделать полный источник для freebitcoins полностью открытым исходным кодом, потому что я не хочу возиться с постоянно работать, чтобы держать эту секретную ценность в секрете. Я должен хеширования весь запрос с помощью секретного ключа и постоянно увеличивающейся нонса, но было лень, и я просто не очень беспокоит атака посредника между Google и мой VPS.
Я мог бы взломать мою копию bitcoind C ++ код для проверки секретного значения в запросах, а также модифицировать его, чтобы он принял подключение из Интернета ... но вместо этого я написал этот маленький прокси-сервер в Python, который работает на тот же блок, bitcoind:
Код:
#
# WSGI Proxy в bitcoind демон (который прослушивает только на 127.0.0.1 для безопасности).
# Rejects без Https соединения или запросы, не POST
# Rejects запросов, которые не включают в себя предварительное общем секретное значение
#
# Apache называет это из-за директивы в /etc/apache2/sites-available/xyz.com
#
импорт hashlib
импорт urllib2
применение четкости (окружать, start_response):
ServerURL = "http://127.0.0.1:8332/"
Защиту error_response (сообщение):
response_headers = [( 'Content-Type', 'текст / обычный'),
( 'Content-Length', ул (Len (сообщение)))]
start_response ( '500 Внутренняя ошибка сервера', response_headers)
возврат сообщения
если environ.get ("HTTPS"знак равно "1":
вернуться error_response ("Незащищенные соединения не допускается.")
Запрос = environ.get ("wsgi.input").читать()
секрет = запрос [0:32]
json_request = запрос [32:]
если hashlib.md5 (" предварительно общий секрет здесь идет "+ Json_request) .hexdigest () = секрет:
вернуться error_response ("Ошибка аутентификации.")
REQ = urllib2.Request (ServerURL, json_request)
ответ = urllib2.urlopen (REQ)
json_response = response.read ()
статус = '200 OK'
response_headers = [( 'Content-Type', 'текст / обычный'),
( 'Content-Length', ул (LEN (json_response)))]
start_response (статус, response_headers)
вернуться [json_response]
Другой конец соединения также Джанго код + Python работает на App Engine:# WSGI Proxy в bitcoind демон (который прослушивает только на 127.0.0.1 для безопасности).
# Rejects без Https соединения или запросы, не POST
# Rejects запросов, которые не включают в себя предварительное общем секретное значение
#
# Apache называет это из-за директивы в /etc/apache2/sites-available/xyz.com
#
импорт hashlib
импорт urllib2
применение четкости (окружать, start_response):
ServerURL = "http://127.0.0.1:8332/"
Защиту error_response (сообщение):
response_headers = [( 'Content-Type', 'текст / обычный'),
( 'Content-Length', ул (Len (сообщение)))]
start_response ( '500 Внутренняя ошибка сервера', response_headers)
возврат сообщения
если environ.get ("HTTPS"знак равно "1":
вернуться error_response ("Незащищенные соединения не допускается.")
Запрос = environ.get ("wsgi.input").читать()
секрет = запрос [0:32]
json_request = запрос [32:]
если hashlib.md5 (" предварительно общий секрет здесь идет "+ Json_request) .hexdigest () = секрет:
вернуться error_response ("Ошибка аутентификации.")
REQ = urllib2.Request (ServerURL, json_request)
ответ = urllib2.urlopen (REQ)
json_response = response.read ()
статус = '200 OK'
response_headers = [( 'Content-Type', 'текст / обычный'),
( 'Content-Length', ул (LEN (json_response)))]
start_response (статус, response_headers)
вернуться [json_response]
Код:
импорт hashlib
импорт jsonrpc
от google.appengine.api импорта UrlFetch
Защиту make_bitcoin_request (server_url, server_secret, метод Params):
json_request = {
"jsonrpc": "2,0",
"Я бы": Ул (time.time ()),
"метод": Метод, "Титулы": Титулы
}
json_string = jsonrpc.dumps (json_request)
секрет = hashlib.md5 (server_secret + json_string) .hexdigest ()
пытаться:
fetch_result = urlfetch.fetch (payment_server,
метод ="ПОСЛЕ", Полезная нагрузка = секрет + json_string,
Заголовки = { 'Content-Type': 'текст / обычный'})
кроме urlfetch.Error, е:
logging.error ( 'make_bitcoin_request не удалось:' ул (е +))
logging.error ( 'Запрос:' + json_string)
возвращения None
если fetch_result.status_code = 200:
logging.error ( 'make_bitcoin_request не удалось; UrlFetch код состояния% d' % (fetch_result.status_code))
logging.error ( 'Запрос:' + json_string)
возвращения None
г = jsonrpc.loads (fetch_result.content)
если г [ «ошибки»] не является None:
logging.error ( 'make_bitcoin_request не удалось, ошибка JSON возвращается')
logging.error ( 'Запрос:' + json_string)
logging.error ( 'Результат:' + fetch_result.content)
возвращения None
возвращение г [ «результат»]
импорт jsonrpc
от google.appengine.api импорта UrlFetch
Защиту make_bitcoin_request (server_url, server_secret, метод Params):
json_request = {
"jsonrpc": "2,0",
"Я бы": Ул (time.time ()),
"метод": Метод, "Титулы": Титулы
}
json_string = jsonrpc.dumps (json_request)
секрет = hashlib.md5 (server_secret + json_string) .hexdigest ()
пытаться:
fetch_result = urlfetch.fetch (payment_server,
метод ="ПОСЛЕ", Полезная нагрузка = секрет + json_string,
Заголовки = { 'Content-Type': 'текст / обычный'})
кроме urlfetch.Error, е:
logging.error ( 'make_bitcoin_request не удалось:' ул (е +))
logging.error ( 'Запрос:' + json_string)
возвращения None
если fetch_result.status_code = 200:
logging.error ( 'make_bitcoin_request не удалось; UrlFetch код состояния% d' % (fetch_result.status_code))
logging.error ( 'Запрос:' + json_string)
возвращения None
г = jsonrpc.loads (fetch_result.content)
если г [ «ошибки»] не является None:
logging.error ( 'make_bitcoin_request не удалось, ошибка JSON возвращается')
logging.error ( 'Запрос:' + json_string)
logging.error ( 'Результат:' + fetch_result.content)
возвращения None
возвращение г [ «результат»]
Я доволен тем, как он работает. Мое самое большое беспокойство в том, что процесс bitcoind может неожиданно выйти, или заполнить диск с debug.log сообщениями, или просто вообще быть отслаиваться. Но до сих пор так хорошо ...