Поддерживает ли Cohttp_mirage.Client TLS?
Кто-нибудь может подтвердить, поддерживает ли Cohttp_mirage.Client TLS (https)? Похоже, что выполненное мной копание указывает на то, что Conduit_mirage поддерживает клиентские tls, но в Cohttp_mirage, в то время как сервер является функтором, принимающим поток, который может быть tcp или tls (как видно из файла mirage-www dispatch_tls.ml).
Если он поддерживает TLS, есть ли примеры, как это настроить (для Mirage)? Я не мог найти что-либо в Интернете или в мираж-скелете. Я пишу клиент для одного веб-сервиса, так что я предполагаю, что ему нужен только один сертификат.
Если ответ "нет, он не поддерживает TLS", выполняется ли над этим какая-либо работа? Возможно, я мог бы попытаться покопаться в себе. Я программирую уже 15 лет, но я все еще довольно новичок в OCaml.
2 ответа
Я не понимаю ваш вопрос, так как вы говорите, что mirage-http поддерживает TLS - так где вы застряли? Я полагаю, вам нужно передать канал с поддержкой TLS connect_uri
,
На стороне сервера веб-сайт проекта ( https://mirage.io/) представляет собой уникальное ядро, поддерживающее TLS.
Примеры проектов (хотя все серверы, но клиент тоже должен работать):
- https://github.com/samoht/mirage-seal (обслуживать статический каталог через https)
- https://github.com/talex5/cuekeeper (серверная часть для клиента CueKeeper GTD, общение через https с браузером)
- BTC Piñata работает как клиент и сервер, используя TLS: http://ownme.ipredator.se/ (но действует только как сервер для HTTP).
Как уже упоминалось, проблема заключается в передаче канала с поддержкой TLS конечному клиенту Cohttp. Вот мой мираж "config.ml" файл.
open Mirage
let net =
try match Sys.getenv "NET" with
| "direct" -> `Direct
| "socket" -> `Socket
| _ -> `Direct
with Not_found -> `Socket
let dhcp =
try match Sys.getenv "DHCP" with
| "" -> false
| _ -> true
with Not_found -> false
let stack console =
match net, dhcp with
| `Direct, true -> direct_stackv4_with_dhcp console tap0
| `Direct, false -> direct_stackv4_with_default_ipv4 console tap0
| `Socket, _ -> socket_stackv4 console [Ipaddr.V4.any]
let main =
foreign "MyDispatch.Main" (console @-> http @-> resolver @-> conduit @-> job)
let () =
let sv4 = stack default_console in
let res_dns = resolver_dns sv4 in
let conduit = conduit_direct ~tls:true sv4 in
let http_srv = http_server conduit ind
register "ident" [
main $ default_console $ http_srv $ res_dns $ conduit
]
Обратите внимание, что мне также нужен DNS для работы http-клиента. Критическая часть ~tls:true
в
let conduit = conduit_direct ~tls:true sv4 in ...
В файле отправки (MyDispatch.ml, чтобы избежать конфликтов имен, у меня есть:
open Lwt
open Cohttp
open Printf
open V1_LWT
module Main (C:CONSOLE) (S:Cohttp_lwt.Server) (RES: Resolver_lwt.S) (CON: Conduit_mirage.S) = struct
module SH = ServiceHandlers.Make (Cohttp_mirage.Client)
module Wm = SH.Wm
let routes ctx = [
("/v1/ident/initiate", fun () -> new SH.initiate_session ctx );
]
let callback ctx (ch,conn) request body =
Wm.dispatch' (routes ctx) ~body ~request
>|= begin function
| None -> (`Not_found, Header.init (), `String "Not found", [])
| Some result -> result
end
>>= fun (status, headers, body, path) ->
let path =
match Sys.getenv "DEBUG_PATH" with
| _ -> Printf.sprintf " - %s" (String.concat ", " path)
| exception Not_found -> ""
in
Printf.eprintf "%d - %s %s%s"
(Code.code_of_status status)
(Code.string_of_method (Request.meth request))
(Uri.path (Request.uri request))
path;
S.respond ~headers ~body ~status ()
let start c http (res_dns) (ctx:CON.t) =
let ctx = Cohttp_mirage.Client.ctx res_dns ctx in
let callback = callback ctx in
let conn_closed (_,conn_id) =
let cid = Cohttp.Connection.to_string conn_id in
C.log c (Printf.sprintf "conn %s closed" cid)
in
http (`TCP 8080) (S.make ~conn_closed ~callback ())
end
Здесь критической частью является добавление перезапуска DNS в контекст (TLS включен) и передача его в обратный вызов, чтобы он мог в конечном итоге использоваться клиентом. ServiceHandlers
использует Webmachine и является функтором, принимающим Cohttp_lwt.Client
модуль (Cohttp_lwt_mirage.Client
, в этом случае). В конечном счете, клиент использует контекст с поддержкой TLS/DNS для выполнения вызова (handle_response
это конкретный код приложения.):
Client.post ~ctx:ctx_with_tls_dns ~headers ~body uri >>= handle_response
"Это легко, когда ты умеешь (тм)". Обратите внимание, что до сих пор я запускал только Mirage/unix, а не Mirage/xen.