hogeとはワイルドカードのようなものです。日々起こった、さまざまなこと −すなわちワイルドカード− を取り上げて日記を書く、という意味で名付けたのかというとそうでもありません。適当に決めたらこんな理由が浮かんできました。
12/16/2018 ふむ [長年日記]
tDiary 5897日目
■ [Py][小ネタ] NAPT 前のアドレスを知る
例えば下記のようなネットワークがあるとする.Client が Web Server にアクセスした際,NAPT Router によって NAPT される前の Client の情報を Web Server が知りたいとする.
+--------+ +-------------+ +------------+ | Client |----------| NAPT Router |--------| Web Server | +--------+ +-------------+ +------------+ 172.16.0.193 172.16.0.1 10.207.9.88 10.207.9.87
NAPT Router が Linux 箱なら,conntrack エントリがカーネルの中に保持されているので,下記のようなサービスを NAPT Router の上で動かしておくことができるだろう.
import flask from pyroute2.netlink.exceptions import NetlinkError from pyroute2.netlink.nfnetlink.nfctsocket import NFCTSocket, NFCTAttrTuple app = flask.Flask(__name__) cts = NFCTSocket() @app.route('/conntrack', methods=['GET']) def conntrack_get(): saddr = flask.request.args.get('saddr') daddr = flask.request.args.get('daddr') proto = int(flask.request.args.get('proto')) sport = int(flask.request.args.get('sport')) dport = int(flask.request.args.get('dport')) tpl = NFCTAttrTuple(saddr=saddr, daddr=daddr, proto=proto, sport=sport, dport=dport) try: entry = cts.entry('get', tuple_reply=tpl) except NetlinkError: return flask.Response(status=404) tuple_orig = entry[0].get_attr('CTA_TUPLE_ORIG') tuple_ip = tuple_orig.get_attr('CTA_TUPLE_IP') tuple_proto = tuple_orig.get_attr('CTA_TUPLE_PROTO') return flask.jsonify(saddr=tuple_ip.get_attr('CTA_IP_V4_SRC'), daddr=tuple_ip.get_attr('CTA_IP_V4_DST'), proto=tuple_proto.get_attr('CTA_PROTO_NUM'), sport=tuple_proto.get_attr('CTA_PROTO_SRC_PORT'), dport=tuple_proto.get_attr('CTA_PROTO_DST_PORT')) if __name__ == '__main__': app.run('10.207.9.88')
その上で Web Server が下記のように,このサービスを叩く.
import flask import requests app = flask.Flask(__name__) @app.route('/', methods=['GET']) def root(): saddr = flask.request.environ['SERVER_NAME'] daddr = flask.request.environ['REMOTE_ADDR'] sport = flask.request.environ['SERVER_PORT'] dport = flask.request.environ['REMOTE_PORT'] response = requests.get('http://10.207.9.88:5000/conntrack?' 'saddr=%(saddr)s&daddr=%(daddr)s&proto=6&' 'sport=%(sport)s&dport=%(dport)s' % locals()) if not response.ok: return flask.Response(status=404) entry = response.json() return flask.jsonify(saddr=entry['saddr'], daddr=entry['daddr'], proto=entry['proto'], sport=entry['sport'], dport=entry['dport']) if __name__ == '__main__': app.run('10.207.9.87')
Client から Web Server にアクセスしてみると,
$ curl -s http://10.207.9.87:5000/ | jq . { "daddr": "10.207.9.87", "dport": 5000, "proto": 6, "saddr": "172.16.0.193", "sport": 55208 }
Web Server から,NAPT 前のオリジナルの Client のデータが返ってきていることが確認できる.
だからどうしたぼくドラえもん.