14

次の R スクリプトを検討してください。

con <- socketConnection(host = "localhost", port = 8, server = TRUE, blocking = TRUE, open = "a+b")
close(con = con)

これらの行を .R ファイルとして保存し、その後コマンド ラインから実行すると (Windows 上で) ファイアウォールの警告が生成されます。少なくとも、初回以降に表示される「セキュリティが強化された Windows ファイアウォール」の下に R のルールがない場合。Macでも同じことが起こると言われましたが、自分で確認できませんでした. これをどのように変更して、ローカルホストのループバックを許可し、ポップアップを回避できますか?

コンテキスト: 並列処理を (1 つのローカル マシンで) 使用する人向けのコードをいくつか書きました。しかし、この警告が画面に表示され、不審に思いました。愚かなことに、人々が [いいえ] をクリックしたり、ポップアップを無視したりしても、並列処理は機能しているように見えます。これは、このコードを変更して、このポップアップを表示せずに引き続き機能することが可能であることを示しています。

他の言語 ( 123 ) で非常によく似た質問を見たことがありますが、R で同じことができるかどうか疑問に思っていました。

Windows 10 ファイアウォールの初回プロンプトの例:

ここに画像の説明を入力してください

4

4 に答える 4

5

(ファイアウォール ルールに関する私の見解については、一番最後を参照してください)

機能は単に存在しないようです。

C では、 と の呼び出しでサーバー ソケットを作成しsocketbind呼び出しlistenで着信接続を取得しacceptます。src\modules\internet\sock.c はソケット ハンドラー コードで、ソケットを開くための 2 つの関数があり、ソケットをSock_connect開いて接続するため、これはクライアント側用でありint Sock_open(Sock_port_t port, Sock_error_t perr)、サーバー ソケット (および実際の受け入れコールは にありますSock_listen)。問題は、これSock_openにはport引数しかなく、ホスト/インターフェースがハードコードされていることです:

/* open a socket for listening */
int Sock_open(Sock_port_t port, Sock_error_t perr)
{
    int sock;
    struct sockaddr_in server;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return Sock_error(perr, errno, 0);

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons((short)port);

    if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
        (listen(sock, MAXBACKLOG) < 0)) {
        close(sock);
        return Sock_error(perr, errno, 0);
    }
    return sock;
}

これは、PC のすべてのインターフェイス (ループバックだけでなく) を意味する INADDR_ANY にバインドしてリッスンし、ファイアウォールを確実にトリガーします。

この関数は、隣接する Rsock.c から呼び出されますが、ポート引数は 1 つだけです。他のすべてが失われる場所は、sockconn.c の 1 ステップ前のようです。

static Rboolean sock_open(Rconnection con)
{
    Rsockconn this = (Rsockconn)con->private;
    int sock, sock1, mlen;
    int timeout = this->timeout;
    char buf[256];

    if(timeout == NA_INTEGER || timeout <= 0) timeout = 60;
    this->pend = this->pstart = this->inbuf;

    if(this->server) {
        sock1 = R_SockOpen(this->port);

この最後の行は、RSockconn のホスト部分が無視される場所ですが、そのようなフィールドが含まれています。

/* used in internet module */
typedef struct sockconn {
    int port;
    int server;
    int fd;
    int timeout;
    char *host;
    char inbuf[4096], *pstart, *pend;
} *Rsockconn;

(これは外部の src\include\Rconnections.h で定義されています)

残念ながら、これで問題が解決するわけではありません。これが問題を抱えている理由です。R の開発者にエラー レポートを提出することを検討してください。コメントは、ファイアウォールやインターネット セキュリティが現在のようにそれほど重要ではなかった古代からネット コードを入手したことを示唆しています。

/* Simple sockets interface derived from the sockets UICI
   implementation in Appendix B of Practical UNIX Programming,
   K. A. Robbins and S. Robbins, Prentice Hall, 1996. */

21年前の話です。


もともと私は他の人から netsh を盗むつもりはありませんでしたが、間違った提案を受ける可能性があると思います。実際には、何も許可してはいけませんが、すべてをブロックしてください:

netsh advfirewall firewall add rule name="Rtest" dir=in action=block program="<location and name of your executable>"

それだけです。問題は、ループバック インターフェイスがまったくファイアウォールで保護されていないことです (したがって、127.0.0.1 への接続は常に機能します。安全のために、私もテストしました)。他の回答で「許可」を見ましたが、それは望ましくありません。他の用途によっては、「localport=8」や「protocol=tcp」でルールを制限する必要があるかもしれませんが、ブロック部分は確実です。

于 2017-11-28T20:57:46.410 に答える