gethostbynameを使用してルートアクセスなしでホスト名にエイリアスを追加するにはどうすればよいですか?

gethostbynameを使用してルートアクセスなしでホスト名にエイリアスを追加するにはどうすればよいですか?

私は(ソースコードで)プログラムを実行しています:

gethostbyname("whatever");

ローカルコンピュータのアドレスを使いたいです。ソースを変更できません。ルートであれば簡単です。 / etc / hostsに名前のエイリアスを指定するだけです。しかし、人間として私ができることはありますか?ホストではないユーザーが私の通話にgethostbyname()同じ影響を与えますか?

/etc/nsswitch.conf持っている:

hosts:      files nis dns myhostname

場合に。

答え1

コンテナで実行

使用ポッドキャスト(またはルートなしのDocker)エイリアスが設定されたコンテナ内でコードを実行できます。たとえば、次を呼び出すコードがありますgethostbyname

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>

int main(int argc, char **argv) {
  for (int i = 1; i < argc; i++) {
    struct hostent *entry = gethostbyname(argv[i]);

    for (int j = 0; entry->h_addr_list[j] != NULL; j++) {
      printf("%s: %s\n", entry->h_name,
             inet_ntoa(*(struct in_addr *)entry->h_addr_list[j]));
    }
  }
  return 0;
}

これをコマンドでコンパイルlookuphostして実行すると、次のような./lookuphost google.com結果が表示されます。

$ ./lookuphost google.com
google.com: 142.251.32.110

google.com問題を解決したい場合は、1.2.3.4次のようにできます。

$ podman run -it --rm \
  --add-host google.com:1.2.3.4 \
  -v $PWD:$PWD -w $PWD fedora:37 \
  ./lookuphost google.com
google.com: 1.2.3.4

関数を使用して挿入

あなたはそれを使用することができます関数の挿入gethostbyname独自のコードで通話を終了します。たとえば、次のように入力するとgethostbyname.c

#define _GNU_SOURCE

#include <arpa/inet.h>
#include <dlfcn.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>

struct hostent *gethostbyname(const char *name) {
  static struct hostent *(*real_gethostbyname)(const char *) = NULL;

  if (!real_gethostbyname) {
    real_gethostbyname = dlsym(RTLD_NEXT, "gethostbyname");
  }

  struct hostent *entry = real_gethostbyname(name);

  if (strcmp(name, "google.com") == 0) {
    struct in_addr inp;

    inet_aton("1.2.3.4", &inp);
    entry->h_addr_list[0] = (char *)&inp;
  }

  return entry;
}

その後、共有ライブラリにビルドします。

gcc -c -fPIC gethostbyname.c
gcc -shared -ldl -fPIC gethostbyname.o -o gethostbyname.so

LD_PRELOAD実行してlookuphost期待される回答を得ることができます。

$ LD_PRELOAD=./gethostbyname.so ./lookuphost google.com
google.com: 1.2.3.4

答え2

  • 使用nss_wrapperライブラリをプリロードします。 @larsksの提案と似ていますが、少し低いレベルで動作します(passwdとホストエミュレーションを提供)。 Sambaはこれをテストスイートに使用します。

    export LD_PRELOAD=libnss_wrapper.so
    export NSS_WRAPPER_HOSTS=/path/to/your/hosts
    
  • glibcに慣れるこれには特定の機能があります。$HOSTALIASESペアリストalias real.hostname.tld(つまり、追加レベルの間接参照、いいえIPアドレスを指します)。

    $ export HOSTALIASES=~/.hosts
    $ cat > $HOSTALIASES <<!
    whatever   real.example.net
    !
    

    しかし、私はこの機能を削除する予定があると思いますが、少なくとも私のシステムではもう機能しないようですgetent hosts。以前のGlibcを使用してディストリビューションを実行している場合、この機能はまだ機能できます。

関連情報