mirror of https://github.com/oxen-io/lokinet
more auth shit
This commit is contained in:
parent
0d6e3bcd89
commit
3cdca30a74
|
@ -4,46 +4,50 @@ import sys
|
|||
|
||||
from socket import AF_INET
|
||||
|
||||
import requests
|
||||
import zmq
|
||||
from pyroute2 import IPRoute
|
||||
|
||||
class LokinetRPC:
|
||||
|
||||
def __init__(self, url):
|
||||
self._rpc_context = zmq.Context()
|
||||
self._rpc_socket = self._rpc_context.socket(zmq.DEALER)
|
||||
self._rpc_socket.setsockopt(zmq.CONNECT_TIMEOUT, 5000)
|
||||
self._rpc_socket.setsockopt(zmq.HANDSHAKE_IVL, 5000)
|
||||
self._rpc_socket.connect(url)
|
||||
self._url = url
|
||||
|
||||
def _jsonrpc(self, method, params={}):
|
||||
r = requests.post(
|
||||
self._url,
|
||||
headers={"Content-Type": "application/json", "Host": "localhost"},
|
||||
json={
|
||||
"jsonrpc": "2.0",
|
||||
"id": "0",
|
||||
"method": "{}".format(method),
|
||||
"params": params,
|
||||
},
|
||||
)
|
||||
return r.json()
|
||||
def rpc(self, method):
|
||||
self._rpc_socket.send_multipart([method.encode(), b'lokinet_vpn'+method.encode()])
|
||||
if not self._rpc_socket.poll(timeout=50):
|
||||
return
|
||||
reply = self._rpc_socket.recv_multipart()
|
||||
if len(reply) >= 3 and reply[0:2] == [b'REPLY', b'lokinet_vpn'+method.encode()]:
|
||||
return reply[2].decode()
|
||||
|
||||
def get_first_hops(self):
|
||||
data = self._jsonrpc("llarp.admin.dumpstate")
|
||||
data = self.rpc("llarp.status")
|
||||
for link in data['result']['links']['outbound']:
|
||||
for session in link["sessions"]['established']:
|
||||
yield session['remoteAddr']
|
||||
|
||||
def close(self):
|
||||
self._rpc_socket.close(linger=0)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--rpc", type=str, default='127.0.0.1:1190')
|
||||
ap.add_argument("--rpc", type=str, default='tcp://127.0.0.1:1190')
|
||||
ap.add_argument("--ifname", type=str, default="lokitun0")
|
||||
ap.add_argument("--up", action='store_const', dest='action', const='up')
|
||||
ap.add_argument("--down", action='store_const', dest='action', const='down')
|
||||
args = ap.parse_args()
|
||||
rpc = LokinetRPC('http://{}/jsonrpc'.format(args.rpc))
|
||||
rpc = LokinetRPC(args.rpc)
|
||||
hops = dict()
|
||||
for hop in rpc.get_first_hops():
|
||||
ip = hop.split(':')[0]
|
||||
hops[ip] = 0
|
||||
rpc.close()
|
||||
if len(hops) == 0:
|
||||
print("lokinet is not connected yet")
|
||||
return 1
|
||||
|
|
|
@ -957,7 +957,9 @@ namespace libuv
|
|||
return;
|
||||
if (h->data && uv_is_active(h) && h->type != UV_TIMER && h->type != UV_POLL)
|
||||
{
|
||||
static_cast<glue*>(h->data)->Close();
|
||||
auto glue = reinterpret_cast<libuv::glue*>(h->data);
|
||||
if (glue)
|
||||
glue->Close();
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
|
|
|
@ -12,6 +12,22 @@
|
|||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
constexpr uint32_t ipv6_flowlabel_mask = 0b00000000000011111111111111111111;
|
||||
|
||||
void
|
||||
ipv6_header::FlowLabel(llarp::nuint32_t label)
|
||||
{
|
||||
// the ipv6 flow label is the last 20 bits in the first 32 bits of the header
|
||||
preamble.flowlabel =
|
||||
(htonl(ipv6_flowlabel_mask) & label.n) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask));
|
||||
}
|
||||
|
||||
llarp::nuint32_t
|
||||
ipv6_header::FlowLabel() const
|
||||
{
|
||||
return llarp::nuint32_t{preamble.flowlabel & htonl(ipv6_flowlabel_mask)};
|
||||
}
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace net
|
||||
|
@ -334,7 +350,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst)
|
||||
IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst, std::optional<nuint32_t> flowlabel)
|
||||
{
|
||||
const size_t ihs = 4 + 4 + 16 + 16;
|
||||
|
||||
|
@ -343,6 +359,11 @@ namespace llarp
|
|||
return;
|
||||
|
||||
auto hdr = HeaderV6();
|
||||
if (flowlabel.has_value())
|
||||
{
|
||||
// set flow label if desired
|
||||
hdr->FlowLabel(*flowlabel);
|
||||
}
|
||||
|
||||
const auto oldSrcIP = hdr->srcaddr;
|
||||
const auto oldDstIP = hdr->dstaddr;
|
||||
|
@ -420,7 +441,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
IPPacket::ZeroAddresses()
|
||||
IPPacket::ZeroAddresses(std::optional<nuint32_t> flowlabel)
|
||||
{
|
||||
if (IsV4())
|
||||
{
|
||||
|
@ -428,12 +449,12 @@ namespace llarp
|
|||
}
|
||||
else if (IsV6())
|
||||
{
|
||||
UpdateIPv6Address({0}, {0});
|
||||
UpdateIPv6Address({0}, {0}, flowlabel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPPacket::ZeroSourceAddress()
|
||||
IPPacket::ZeroSourceAddress(std::optional<nuint32_t> flowlabel)
|
||||
{
|
||||
if (IsV4())
|
||||
{
|
||||
|
@ -441,9 +462,10 @@ namespace llarp
|
|||
}
|
||||
else if (IsV6())
|
||||
{
|
||||
UpdateIPv6Address({0}, {ntoh128(dstv6().h)});
|
||||
UpdateIPv6Address({0}, {ntoh128(dstv6().h)}, flowlabel);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<IPPacket>
|
||||
IPPacket::MakeICMPUnreachable() const
|
||||
{
|
||||
|
|
|
@ -75,16 +75,33 @@ typedef struct ip_hdr
|
|||
#define tot_len ip_total_length
|
||||
#endif
|
||||
|
||||
struct ipv6_header
|
||||
struct ipv6_header_preamble
|
||||
{
|
||||
unsigned char version : 4;
|
||||
unsigned char pad_small : 4;
|
||||
uint8_t pad[3];
|
||||
};
|
||||
|
||||
struct ipv6_header
|
||||
{
|
||||
union {
|
||||
ipv6_header_preamble preamble;
|
||||
uint32_t flowlabel;
|
||||
} preamble;
|
||||
|
||||
uint16_t payload_len;
|
||||
uint8_t proto;
|
||||
uint8_t hoplimit;
|
||||
in6_addr srcaddr;
|
||||
in6_addr dstaddr;
|
||||
|
||||
/// get 20 bit truncated flow label in network order
|
||||
llarp::nuint32_t
|
||||
FlowLabel() const;
|
||||
|
||||
/// put 20 bit truncated flow label network order
|
||||
void
|
||||
FlowLabel(llarp::nuint32_t flowlabel);
|
||||
};
|
||||
|
||||
#include <memory>
|
||||
|
@ -242,14 +259,16 @@ namespace llarp
|
|||
UpdateIPv4Address(nuint32_t src, nuint32_t dst);
|
||||
|
||||
void
|
||||
UpdateIPv6Address(huint128_t src, huint128_t dst);
|
||||
UpdateIPv6Address(
|
||||
huint128_t src, huint128_t dst, std::optional<nuint32_t> flowlabel = std::nullopt);
|
||||
|
||||
/// set addresses to zero and recacluate checksums
|
||||
void
|
||||
ZeroAddresses();
|
||||
ZeroAddresses(std::optional<nuint32_t> flowlabel = std::nullopt);
|
||||
|
||||
/// zero out source address
|
||||
void
|
||||
ZeroSourceAddress();
|
||||
ZeroSourceAddress(std::optional<nuint32_t> flowlabel = std::nullopt);
|
||||
|
||||
/// make an icmp unreachable reply packet based of this ip packet
|
||||
std::optional<IPPacket>
|
||||
|
|
|
@ -36,21 +36,40 @@ namespace llarp::rpc
|
|||
|
||||
void
|
||||
EndpointAuthRPC::AuthenticateAsync(
|
||||
llarp::service::Address from,
|
||||
llarp::service::ConvoTag,
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg,
|
||||
std::function<void(service::AuthResult)> hook)
|
||||
{
|
||||
const auto from = msg->sender.Addr();
|
||||
if (m_AuthWhitelist.count(from))
|
||||
{
|
||||
// explicitly whitelisted source
|
||||
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthAccepted); });
|
||||
return;
|
||||
}
|
||||
if (not m_Conn.has_value())
|
||||
{
|
||||
// we don't have a connection to the backend so it's failed
|
||||
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthFailed); });
|
||||
return;
|
||||
}
|
||||
// call method with 1 parameter: the loki address of the remote
|
||||
|
||||
if (msg->proto != llarp::service::eProtocolAuth)
|
||||
{
|
||||
// not an auth message, reject
|
||||
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthRejected); });
|
||||
return;
|
||||
}
|
||||
|
||||
const auto maybe = msg->MaybeEncodeAuthInfo();
|
||||
if (not maybe.has_value())
|
||||
{
|
||||
// cannot generate meta info, failed
|
||||
m_Endpoint->RouterLogic()->Call([hook]() { hook(service::AuthResult::eAuthFailed); });
|
||||
return;
|
||||
}
|
||||
std::string_view metaInfo{(char*)maybe->data(), maybe->size()};
|
||||
std::string_view payload{(char*)msg->payload.data(), msg->payload.size()};
|
||||
// call method with 2 parameters: metainfo and userdata
|
||||
m_LMQ->request(
|
||||
*m_Conn,
|
||||
m_AuthMethod,
|
||||
|
@ -67,7 +86,8 @@ namespace llarp::rpc
|
|||
}
|
||||
self->m_Endpoint->RouterLogic()->Call([hook, result]() { hook(result); });
|
||||
},
|
||||
from.ToString());
|
||||
metaInfo,
|
||||
payload);
|
||||
} // namespace llarp::rpc
|
||||
|
||||
} // namespace llarp::rpc
|
||||
|
|
|
@ -30,8 +30,7 @@ namespace llarp::rpc
|
|||
|
||||
void
|
||||
AuthenticateAsync(
|
||||
llarp::service::Address from,
|
||||
service::ConvoTag tag,
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg,
|
||||
std::function<void(service::AuthResult)> hook) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace llarp::service
|
|||
/// result later
|
||||
virtual void
|
||||
AuthenticateAsync(
|
||||
service::Address from, service::ConvoTag tag, std::function<void(AuthResult)> hook) = 0;
|
||||
std::shared_ptr<llarp::service::ProtocolMessage> msg,
|
||||
std::function<void(AuthResult)> hook) = 0;
|
||||
};
|
||||
} // namespace llarp::service
|
||||
|
|
|
@ -854,11 +854,12 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
Endpoint::AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthResult)> hook)
|
||||
Endpoint::AsyncProcessAuthMessage(
|
||||
std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook)
|
||||
{
|
||||
if (m_AuthPolicy)
|
||||
{
|
||||
m_AuthPolicy->AuthenticateAsync(std::move(addr), std::move(tag), std::move(hook));
|
||||
m_AuthPolicy->AuthenticateAsync(std::move(msg), std::move(hook));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -355,7 +355,8 @@ namespace llarp
|
|||
IntroSetPublished();
|
||||
|
||||
void
|
||||
AsyncAuthConvoTag(Address addr, ConvoTag tag, std::function<void(AuthResult)> hook);
|
||||
AsyncProcessAuthMessage(
|
||||
std::shared_ptr<ProtocolMessage> msg, std::function<void(AuthResult)> hook);
|
||||
|
||||
void
|
||||
SendAuthReject(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult st);
|
||||
|
|
|
@ -73,10 +73,13 @@ namespace llarp
|
|||
return false;
|
||||
if (!BEncodeWriteDictInt("a", proto, buf))
|
||||
return false;
|
||||
if (!bencode_write_bytestring(buf, "d", 1))
|
||||
return false;
|
||||
if (!bencode_write_bytestring(buf, payload.data(), payload.size()))
|
||||
return false;
|
||||
if (not payload.empty())
|
||||
{
|
||||
if (!bencode_write_bytestring(buf, "d", 1))
|
||||
return false;
|
||||
if (!bencode_write_bytestring(buf, payload.data(), payload.size()))
|
||||
return false;
|
||||
}
|
||||
if (!BEncodeWriteDictEntry("i", introReply, buf))
|
||||
return false;
|
||||
if (!BEncodeWriteDictInt("n", seqno, buf))
|
||||
|
@ -93,6 +96,32 @@ namespace llarp
|
|||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
std::optional<std::vector<byte_t>>
|
||||
ProtocolMessage::MaybeEncodeAuthInfo() const
|
||||
{
|
||||
std::array<byte_t, 1024> info;
|
||||
llarp_buffer_t buf{info};
|
||||
if (not bencode_start_dict(&buf))
|
||||
return std::nullopt;
|
||||
if (not BEncodeWriteDictInt("a", proto, &buf))
|
||||
return std::nullopt;
|
||||
if (not BEncodeWriteDictEntry("i", introReply, &buf))
|
||||
return std::nullopt;
|
||||
if (not BEncodeWriteDictEntry("s", sender, &buf))
|
||||
return std::nullopt;
|
||||
if (not BEncodeWriteDictEntry("t", tag, &buf))
|
||||
return std::nullopt;
|
||||
if (not BEncodeWriteDictInt("v", version, &buf))
|
||||
return std::nullopt;
|
||||
if (not bencode_end(&buf))
|
||||
return std::nullopt;
|
||||
const std::size_t encodedSize = buf.cur - buf.base;
|
||||
std::vector<byte_t> data;
|
||||
data.resize(encodedSize);
|
||||
std::copy_n(buf.base, encodedSize, data.data());
|
||||
return data;
|
||||
}
|
||||
|
||||
ProtocolFrame::~ProtocolFrame() = default;
|
||||
|
||||
bool
|
||||
|
@ -335,10 +364,8 @@ namespace llarp
|
|||
path::Path_ptr path = std::move(self->path);
|
||||
const PathID_t from = self->frame.F;
|
||||
msg->handler = self->handler;
|
||||
|
||||
self->handler->AsyncAuthConvoTag(
|
||||
msg->sender.Addr(),
|
||||
msg->tag,
|
||||
self->handler->AsyncProcessAuthMessage(
|
||||
msg,
|
||||
[path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey](
|
||||
AuthResult result) {
|
||||
if (result == AuthResult::eAuthAccepted)
|
||||
|
|
|
@ -50,6 +50,10 @@ namespace llarp
|
|||
uint64_t seqno = 0;
|
||||
uint64_t version = LLARP_PROTO_VERSION;
|
||||
|
||||
/// maybe encode metainfo for lmq endpoint auth
|
||||
std::optional<std::vector<byte_t>>
|
||||
MaybeEncodeAuthInfo() const;
|
||||
|
||||
bool
|
||||
DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val);
|
||||
|
||||
|
|
|
@ -10,4 +10,5 @@ namespace llarp::service
|
|||
constexpr ProtocolType eProtocolTrafficV4 = 1UL;
|
||||
constexpr ProtocolType eProtocolTrafficV6 = 2UL;
|
||||
constexpr ProtocolType eProtocolExit = 3UL;
|
||||
constexpr ProtocolType eProtocolAuth = 4UL;
|
||||
} // namespace llarp::service
|
||||
|
|
|
@ -142,7 +142,6 @@ RunIWPTest(Func_t test, Duration_t timeout = 1s)
|
|||
{
|
||||
// shut up logs
|
||||
llarp::LogSilencer shutup;
|
||||
|
||||
// set up event loop
|
||||
auto logic = std::make_shared<llarp::Logic>();
|
||||
auto loop = llarp_make_ev_loop();
|
||||
|
|
Loading…
Reference in New Issue