firewall: obfuscate OpenChannelSync

This commit is contained in:
bitromortac 2024-05-31 12:31:45 +02:00
parent 275a882e96
commit bca729a5af
No known key found for this signature in database
GPG key ID: 1965063FC13BEBE2
2 changed files with 257 additions and 0 deletions

View file

@ -305,6 +305,13 @@ func (p *PrivacyMapper) checkers(db firewalldb.PrivacyMapDB,
handleBatchOpenChannelResponse(db, flags),
mid.PassThroughErrorHandler,
),
"/lnrpc.Lightning/OpenChannelSync": mid.NewFullRewriter(
&lnrpc.OpenChannelRequest{},
&lnrpc.ChannelPoint{},
handleChannelOpenRequest(db, flags),
handleChannelOpenResponse(db, flags),
mid.PassThroughErrorHandler,
),
}
}
@ -1454,6 +1461,157 @@ func handleBatchOpenChannelResponse(db firewalldb.PrivacyMapDB,
}
}
func handleChannelOpenRequest(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags) func(ctx context.Context,
r *lnrpc.OpenChannelRequest) (proto.Message, error) {
return func(_ context.Context, r *lnrpc.OpenChannelRequest) (
proto.Message, error) {
var nodePubkey []byte
err := db.View(func(tx firewalldb.PrivacyMapTx) error {
var err error
// We use the byte slice representation of the
// pubkey and fall back to the hex string if present.
nodePubkey = r.NodePubkey
if len(nodePubkey) == 0 && r.NodePubkeyString != "" {
nodePubkey, err = hex.DecodeString(
r.NodePubkeyString,
)
if err != nil {
return err
}
}
if !flags.Contains(session.ClearPubkeys) {
nodePubkey, err = firewalldb.RevealBytes(
tx, nodePubkey,
)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return nil, err
}
return &lnrpc.OpenChannelRequest{
// Obfuscated fields.
NodePubkey: nodePubkey,
// Omitted fields.
// NodePubkeyString
// Non-obfuscated fields.
SatPerVbyte: r.SatPerVbyte,
LocalFundingAmount: r.LocalFundingAmount,
PushSat: r.PushSat,
TargetConf: r.TargetConf,
SatPerByte: r.SatPerByte,
Private: r.Private,
MinHtlcMsat: r.MinHtlcMsat,
RemoteCsvDelay: r.RemoteCsvDelay,
MinConfs: r.MinConfs,
SpendUnconfirmed: r.SpendUnconfirmed,
CloseAddress: r.CloseAddress,
FundingShim: r.FundingShim,
RemoteMaxValueInFlightMsat: r.RemoteMaxValueInFlightMsat,
RemoteMaxHtlcs: r.RemoteMaxHtlcs,
MaxLocalCsv: r.MaxLocalCsv,
CommitmentType: r.CommitmentType,
ZeroConf: r.ZeroConf,
ScidAlias: r.ScidAlias,
BaseFee: r.BaseFee,
FeeRate: r.FeeRate,
UseBaseFee: r.UseBaseFee,
UseFeeRate: r.UseFeeRate,
RemoteChanReserveSat: r.RemoteChanReserveSat,
FundMax: r.FundMax,
Memo: r.Memo,
Outpoints: r.Outpoints,
}, nil
}
}
func handleChannelOpenResponse(db firewalldb.PrivacyMapDB,
flags session.PrivacyFlags) func(ctx context.Context,
r *lnrpc.ChannelPoint) (proto.Message, error) {
return func(_ context.Context, r *lnrpc.ChannelPoint) (
proto.Message, error) {
var (
txid string
index uint32
)
err := db.Update(func(tx firewalldb.PrivacyMapTx) error {
var err error
txid = r.GetFundingTxidStr()
if len(r.GetFundingTxidBytes()) != 0 {
hash, err := chainhash.NewHash(
r.GetFundingTxidBytes(),
)
if err != nil {
return err
}
txid = hash.String()
}
index = r.OutputIndex
if !flags.Contains(session.ClearChanIDs) {
txid, index, err = firewalldb.HideChanPoint(
tx, txid, index,
)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return nil, err
}
switch {
case len(r.GetFundingTxidBytes()) != 0:
hash, err := chainhash.NewHashFromStr(txid)
if err != nil {
return nil, err
}
return &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: hash[:],
},
OutputIndex: index,
}, nil
case r.GetFundingTxidStr() != "":
return &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidStr{
FundingTxidStr: txid,
},
OutputIndex: index,
}, nil
default:
return nil, fmt.Errorf("channel point has no funding " +
"txid")
}
}
}
// maybeHideAmount hides an amount if the privacy flag is not set.
func maybeHideAmount(flags session.PrivacyFlags, randIntn func(int) (int,
error), a int64) (int64, error) {

View file

@ -728,6 +728,105 @@ func TestPrivacyMapper(t *testing.T) {
},
},
},
{
name: "OpenChannelSync Request",
uri: "/lnrpc.Lightning/OpenChannelSync",
msgType: rpcperms.TypeRequest,
msg: &lnrpc.OpenChannelRequest{
NodePubkey: []byte{
200, 19, 68, 149,
},
LocalFundingAmount: 1_000_000,
PushSat: 1_000_000,
MinHtlcMsat: 100,
},
expectedReplacement: &lnrpc.OpenChannelRequest{
NodePubkey: []byte{
1, 2, 3, 4,
},
LocalFundingAmount: 1_000_000,
PushSat: 1_000_000,
MinHtlcMsat: 100,
},
},
{
name: "OpenChannelSync Request clear",
uri: "/lnrpc.Lightning/OpenChannelSync",
msgType: rpcperms.TypeRequest,
privacyFlags: []session.PrivacyFlag{
session.ClearPubkeys,
},
msg: &lnrpc.OpenChannelRequest{
NodePubkey: []byte{
200, 19, 68, 149,
},
LocalFundingAmount: 1_000_000,
PushSat: 1_000_000,
MinHtlcMsat: 100,
},
expectedReplacement: &lnrpc.OpenChannelRequest{
NodePubkey: []byte{
200, 19, 68, 149,
},
LocalFundingAmount: 1_000_000,
PushSat: 1_000_000,
MinHtlcMsat: 100,
},
},
{
name: "OpenChannelSync Response bytes",
uri: "/lnrpc.Lightning/OpenChannelSync",
msgType: rpcperms.TypeResponse,
msg: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidStr{
FundingTxidStr: clearTxID,
},
OutputIndex: 0,
},
expectedReplacement: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidStr{
FundingTxidStr: obfusTxID0,
},
OutputIndex: obfusOut0,
},
},
{
name: "OpenChannelSync Response string",
uri: "/lnrpc.Lightning/OpenChannelSync",
msgType: rpcperms.TypeResponse,
msg: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: clearTxIDReveresed[:],
},
OutputIndex: 0,
},
expectedReplacement: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: obfusTxID0Reversed[:],
},
OutputIndex: obfusOut0,
},
},
{
name: "OpenChannelSync Response clear",
uri: "/lnrpc.Lightning/OpenChannelSync",
msgType: rpcperms.TypeResponse,
privacyFlags: []session.PrivacyFlag{
session.ClearChanIDs,
},
msg: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: clearTxIDReveresed[:],
},
OutputIndex: 0,
},
expectedReplacement: &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: clearTxIDReveresed[:],
},
OutputIndex: 0,
},
},
}
decodedID := &lnrpc.MacaroonId{