複数の X11 サーバー (Xephyr、Xpra など) 間でクリップボードを共有します。

複数の X11 サーバー (Xephyr、Xpra など) 間でクリップボードを共有します。

潜在的に危険なアプリケーションを実行する予定(ブラウザ等)別の X サーバー上で実行しますが、各サーバーには独自のクリップボードがあるため、あるウィンドウから別のウィンドウにリンク/テキストをコピーすることはできません。

ほとんどの記事では、xclip やその他の同様のユーティリティを使用したスクリプトを使用してこれを行うことを提案しています。

しかし、どうやって正しく誤って新しい脆弱性を作成しないように、共通のクリップボードを作成しますか?

答え1

注: 戦略の変更を反映するために回答を更新します。Xephyr をサーバー/コンテナーで実行する代わりに、ホスト/メイン使用環境で実行しています。その理由は、Xephyr をサーバー/コンテナーで実行することは、正面玄関ではなく内扉に鍵をかけるようなものであり、悪意のある人物が内扉を迂回して、X パイプ リモート ソケットを介して直接クリップボードにアクセスするためです。

クリップボードの脆弱性という同じ問題に直面して、私はホスト (私の個人用ワークスペース) 上で Xephyr を実行し、コンテナ上のサーバーからローカル Xephyr に X を転送することでこの問題に取り組みました。

Xephyr はディスプレイ ':2' で実行されていますが、個人用ワークスペース ウィンドウとブラウザーはデフォルトのディスプレイ ':0' で実行されています。これら 2 つのディスプレイはクリップボードを共有していません。それぞれ独自のクリップボードがあります。これが、ディスプレイ ':0' の個人用ワークスペース クリップボードの覗き見を防ぐ唯一の方法です。次に、ホット キー (ファンクション キーなど) を設定し、1 つはクリップボードの内容を ':0' から ':2' に転送し、もう 1 つは ':2' から ':0' に転送して、完全な制御を可能にしています。

シェルスクリプトではコードは次のようになります

xsel --display :0 --clipboard -o |  xsel --display :2 --clipboard -i

ただし、この投稿の下部に示すように、JavaScript を使用しています。

X転送を開始するためのシェルスクリプトは次のようになります。

Xephyr <args> :2
DISPLAY=:2 ssh -X -R 44713:localhost:4713 user@container <<EOF
DISPLAY=:10 PULSE_SERVER=tcp:localhost:44713 openbox --startup firefox
EOF

ただし、私はそれを実行するために JavaScript プログラムを使用しています。

以下は、ホット キーによってマップされる ':0' と ":2" の間でコピーするための JavaScript コードです。動作を確認するために一時的なメッセージ ボックスがポップアップ表示されます。

#!/usr/bin/env node
`strict`;
const child_process = require('child_process');

// TODO: write unviewable error messasges to system log

function notifySend(title, msg){
  title = title.replace(/"/g, '\\"');
  msg = msg.replace(/"/g, '\\"');
  //msg = msg.replace(/'/g, '\\'')
  try {
    child_process.execSync(`notify-send "${title}" "${msg}"`);
  } catch(e) {
    console.log(`system call "notify-send" failed with ${e.message}`);
  }
}

async function clipXfer(fromDispNum,toDispNum){
  var clipValue;
  let cmd1 = `xsel --display :${fromDispNum} --clipboard --output`;
  let cmd2 = `xsel --display :${toDispNum} --clipboard --input`;
  try {
    clipValue = child_process.execSync(cmd1, { encoding: 'utf-8' });
  } catch(e) {
    throw Error(`Display ${fromDispNum} clipboard is empty`);
  }
  await new Promise((resolve, reject)=>{        
    // eslint-disable-next-line no-unused-vars
    var proc = child_process.exec(cmd2, (error, stdout, stderr) => {
      //if (stdout) console.log(stdout);
      //if (stderr) console.log(stderr);
      if (error) {
        reject(Error(`${error.message}`));
      }
      resolve();
    });
    if (!proc.stdin.write(clipValue))
      reject(Error('clipToCont(), pipe write failed'));
    proc.stdin.end();
  });                    
}


async function main()
{
  let argOff=2;
  if (process.argv.length-argOff<2)
    throw Error('clip-xfer requires two arguments: fromDispNum, toDispNum');
  let fromDispNum = process.argv[argOff];
  let toDispNum = process.argv[argOff+1];
  argOff+=2;
  let f = (outcome)=>{
    notifySend("clipXfer",  `${fromDispNum} => ${toDispNum} ${outcome}`);
  }; 
  await clipXfer(fromDispNum,toDispNum)
    .then(f('SUCCESS'))
    .catch((e)=>{f(`FAILURE, ${e.message}`); throw e;});
}

//console.log(process.argv);
//console.log(process.env);
main()
  .then(()=>{process.exitCode=0;})
  .catch((e)=>{
    console.log(e);
    process.exitCode=1;
  });

答え2

私が使うxクリップシンク98% の確率で動作します。2% の場合は、次のようにします。

表示中:0 実行コピーq展示中:1回パーセライトクリップボードを同期するには

copyq add $(parcellite)

または後方に

copyq read | parcellite -c

100%動作します! :-)

関連情報