2018年12月11日火曜日

OpenDolphinとORCAの連携

第3章の章末問題
第2章の章末問題でやったカルテ例1をOpenDolphinに入力してORCAで診療報酬明細書を作成し、模範解答と比較しなさい。
を実際にやってみたのでまとめておく。

OpenDolphinで過去にさかのぼってカルテは作成できるか?


その前に標題について考える。
カルテ例1は、平成29年4月10日(耳鼻科)、4月17日(耳鼻科と内科)の3日間の診療記録である。したがって過去にさかのぼってカルテを作成しなければならない。
医事会計システムORCAはそれができた。では、電子カルテシステムであるOpenDolphinにそれができるのだろうか?電子カルテなのだから、日付を変える(実際の診療日でない過去の日付に変える)のはカルテの改ざんに当たらないのか・・・。そういう事情があってかどうかは知らないが、OpenDolphinでは日付を変えてカルテを作成する機能はなさそうである。
そこで、カルテ例1の初回の診察日(4/10 耳鼻科)のみ、当日日付で入力するものとする。

診療科の設定と患者の選択


1) OpenDolphinにログインし、メニューから[ツール]→[プロフィール]を選んでこの医師の診療科を「耳鼻いんこう科」に変更する。
図1.プロフィール画面

2) ORCAで 患者受付を行う。
図2.ORCAの患者受付画面

3) OpenDolphinの受付画面にORCAで受け付けた患者が表示されたら、その患者をマウスの右ボタンでクリックして表示されるメニューから「カルテを開く」を選択する。
図3.患者受付画面

カルテの作成


下図に示す画面(インスペクタ画面という)が開いたら、メニューにある[カルテ作成]ボタン([参照]タブの真上にある黄色い星のついたドキュメントアイコン)をクリックする。
図4.インスペクタ画面

すると下図に示す確認画面が出るので、そのまま[OK]ボタンをクリックする。
図5.新規カルテ画面

下図に示す白紙のカルテ画面が現れたら、カルテ例1の4/10分(耳鼻科)の経過記録とオーダを入力する。
図6.白紙のカルテ画面
図7は、こうして入力を終えた画面である。
図7.入力し終えたカルテ画面
カルテを保存するために、メニューのフロッピーマークをクリックすると下図のような確認画面が表示される。
図8.ドキュメント保存

 [タイトル]に相応しい文字列を入力して[保存]を押す。

医事会計システム(ORCA)を確認


電子カルテシステムから入力したオーダが医事会計システムにどのように反映されているかを確認するためにORCAの[診療行為]画面を開いて当該患者のIDを入力した。
図9にその画面を示す。
図9.医事会計システムORCAの診療行為画面
図9から次のことがわかる。
  • 科コード、担当医はOK
  • 再診料(72点)がない
  • B-V(血液採取「1」静脈25点)がない
  • 「院内」処方になっている
  • 各種加算自動発生されてない
    • 明細書発行体制等加算(1点)
    • 時間外対応加算2(3点)
    • 一般名処方加算(3点)
    • 検体検査判断料がない
そこで、[院外]にして登録ボタンを押すと
  • 血液学的検査判断料(125点)
  • 免疫学的検査判断料(144点)
  • 処方せん料(68点)
 が自動発生された。
したがって、以下の項目については手入力した。
  • 再診料(72点)
  • 明細書発行体制等加算(1点)
  • 時間外対応加算2(3点)
  • 一般名処方加算(3点)
  • B-V(血液採取「1」静脈25点)

これらを手入力して[登録]ボタンを押すと、「警告!一般名処方加算(処方せん料)の対象薬剤がありません」という警告メッセージが出たので、オロパタジン塩酸塩とクロモグリク酸ナトリウムをジェネリック医薬品に変更してから[登録]ボタンを押すと警告が出なくなった。単に処方入力を間違っていただけである。

以上より、電子カルテシステムでオーダを入力して、それをORCAへ送信しても、かなりの項目を手入力しなければならないことがわかった。

レセプトの作成

不足分を手入力後 レセプトを作成した。図10に作成したレセプトを示す。
図10.レセプト

パケットキャプチャ


OpenDolphinの受付画面で患者を選んでカルテ画面を開くときのOpenDolphinクライアントとサーバ間の通信をキャプチャした。
その結果、3つのセッションを取得できた。

セッション1(受診履歴)


リスト1は 最初のセッションをキャプチャした結果である。使用するサーバ側のPort番号は8080で、プロトコルはHTTPである。
GET /dolphin/openSource/karte/24,2008-12-11%2012:00:00 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: d844211bc2d60c9dea151d0b3abb6678
userName: 1.3.6.1.4.1.9414.70.1:DR0002
Host: 172.16.111.217:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 1198
Date: Tue, 11 Dec 2018 03:03:43 GMT

{
  "patientVisits": [
    "2018-04-10T10:44:24",
    "2018-12-10T06:18:44",
    "2018-12-09T06:27:19"
  ],
  "docInfoList": [
    {
      "hasRp": true,
      "hasTreatment": false,
      "hasLaboTest": true,
      "hasMark": false,
      "sendLabtest": false,
      "sendMml": false,
      "hasImage": false,
      "title": "耳鼻科(4/10)",
      "facilityName": null,
      "patientId": null,
      "department": "27",
      "firstConfirmDate": 1544494704394,
      "confirmDate": 1544494704394,
      "departmentDesc": "耳鼻いんこう科,27,医師 二郎,10002,JPN332020100008",
      "parentPk": 0,
      "docId": "9afe11a0ac106c2c586f49aafe7e4c86",
      "sendClaim": false,
      "versionNumber": "1.0",
      "parentIdRelation": null,
      "docType": "karte",
      "purpose": "recode",
      "healthInsurance": "31",
      "healthInsuranceDesc": "31 国家共済",
      "healthInsuranceGUID": "75923d6f-a338-4cd5-8cd1-ce60377224e0",
      "claimDate": 1544494668866,
      "patientGender": null,
      "patientName": null,
      "departmentCodeSys": null,
      "docPk": 72,
      "purposeDesc": null,
      "purposeCodeSys": null,
      "healthInsuranceCodeSys": null,
      "versionNotes": null,
      "parentId": null,
      "parentIdDesc": null,
      "parentIdCodeSys": null,
      "labtestOrderNumber": null,
      "pvthealthInsuranceModel": null,
      "createrLisence": null,
      "status": "F"
    }
  ],
  "memoList": null,
  "lastDocDate": 1544494704394,
  "created": "2018-12-08",
  "allergies": null,
  "heights": null,
  "weights": null,
  "id": 26
}
リスト1.受診履歴

1行目はクライアントがリクエスト行に設定したGETコマンドである。「24,2008-12-11%2012:00:00」というキーを指定してRESTful APIを使って患者の受診履歴を要求している。
先頭の「24」は患者を識別するための内部キーかもしれない。カンマに続く「2008-12-11%2012:00:00」はタイムスタンプのようである。「2008/12/11 12:00:00」という意味であろうか?
しかし、カルテを入力したのは2018/12/11である。西暦年が10年も違う。

サーバからのレスポンスはJSON形式になっている。「patientVisits」は見るからに受診日履歴である。年月日時分秒まで記録されている。
「docInfoList」はその配列要素がカルテ概略のようだ。「docId」でカルテと紐づけているのかもしれない。それにしても「patientId」がnullというのは奇妙だ。

セッション2(排他制御?)


2番目のセッションをリスト2に示す。
PUT /dolphin/openSource/chartEvent/event HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Type: application/json
password: d844211bc2d60c9dea151d0b3abb6678
userName: 1.3.6.1.4.1.9414.70.1:DR0002
Content-Length: 293
Host: 172.16.111.217:8080
Connection: Keep-Alive

{
  "state": 1,
  "patientModel": null,
  "ownerUUID": "DR0002:250bb875-b660-4033-8656-4074e0dace83",
  "byomeiCountToday": 0,
  "byomeiCount": 0,
  "facilityId": "1.3.6.1.4.1.9414.70.1",
  "memo": null,
  "issuerUUID": "DR0002:250bb875-b660-4033-8656-4074e0dace83",
  "patientVisitModel": null,
  "eventType": 0,
  "ptPk": 24,
  "pvtPk": 0
}

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 1
Date: Tue, 11 Dec 2018 03:03:43 GMT

1

リスト2.排他制御と思われる通信データ

リスト1と違ってクライアントはPUTメソッドを送っている。RESTful APIではPUTメソッドは更新を意味する。何らかの情報の更新をサーバにリクエストしているものと思われる。
リクエストメッセージのボディ部にあるJSON形式のデータを見ると「ptPk」に「24」という値が設定されている。これが患者を識別するための内部キーであれば、この通信は患者情報を他のプロセスには利用させないようにロックしているのかもしれない。

セッション3


リスト3に示すように、最後のセッションは、サーバがとても長いデータを返送してくる。
GET /dolphin/openSource/karte/documents/72 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: d844211bc2d60c9dea151d0b3abb6678
userName: 1.3.6.1.4.1.9414.70.1:DR0002
Host: 172.16.111.217:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Transfer-Encoding: chunked
Content-Type: application/json
Date: Tue, 11 Dec 2018 03:03:43 GMT

{
  "list": [
    {
      "modules": [
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUHJvZ3Jlc3NDb3Vyc2UiPgogIDx2b2lkIHByb3BlcnR5PSJmcmVlVGV4dCI+CiAgIDxzdHJpbmc+Jmx0O3NlY3Rpb24gc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MTExJnF1b3Q7Jmd0OyZsdDtwYXJhZ3JhcGggc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MjkmcXVvdDsmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MjkmcXVvdDsgbmFtZT0mcXVvdDtjb250ZW50JnF1b3Q7Jmd0OyZsdDt0ZXh0Jmd0O1Mp44CA5LuK5pyI44Gr5YWl44Gj44Gm44CB6by76ZaJ44CB6by75rGB44GM6YW344GP44Gq44KK44CB5LuV5LqL5Lit44KC44Gk44KJ44GECiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDsyOSZxdW90OyBlbmQ9JnF1b3Q7NDkmcXVvdDsmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7MjkmcXVvdDsgZW5kPSZxdW90OzM0JnF1b3Q7IG5hbWU9JnF1b3Q7Y29udGVudCZxdW90OyZndDsmbHQ7dGV4dCZndDtP77yJ44CA6aKo6YKqJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDszNCZxdW90OyBlbmQ9JnF1b3Q7NDcmcXVvdDsgbmFtZT0mcXVvdDtjb250ZW50JnF1b3Q7Jmd0OyZsdDt0ZXh0Jmd0O+eXh+eKtuOBquOBl+OAgeWWmOaBr+OBruaXouW+gOattOOCguOBqiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7NDcmcXVvdDsgZW5kPSZxdW90OzQ5JnF1b3Q7IG5hbWU9JnF1b3Q7Y29udGVudCZxdW90OyZndDsmbHQ7dGV4dCZndDvjgZcKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzQ5JnF1b3Q7IGVuZD0mcXVvdDs5NyZxdW90OyZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDs0OSZxdW90OyBlbmQ9JnF1b3Q7OTcmcXVvdDsgbmFtZT0mcXVvdDtjb250ZW50JnF1b3Q7Jmd0OyZsdDt0ZXh0Jmd0O0HvvI9Q77yJ44CA6by76ZaJ44CB6by75rGB44Gr44Gk44GE44Gm44Gv5a2j56+A55qE44Gq44Ki44Os44Or44Ku44O844KS55aR44GE44CB56K65a6a6Ki65pat44Gu44Gf44KB44GrMemAsemWk+W+jOOBq+aknOafu+e1kOaenOWgseWRigombHQ7L3RleHQmZ3Q7Jmx0Oy9jb250ZW50Jmd0OyZsdDsvcGFyYWdyYXBoJmd0OyZsdDtwYXJhZ3JhcGggc3RhcnQ9JnF1b3Q7OTcmcXVvdDsgZW5kPSZxdW90OzExMSZxdW90OyZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDs5NyZxdW90OyBlbmQ9JnF1b3Q7MTEwJnF1b3Q7IG5hbWU9JnF1b3Q7Y29udGVudCZxdW90OyZndDsmbHQ7dGV4dCZndDvlhoXmnI3olqzlj4rjgbPlpJbnlKjolqzjgafntYzpgY7oprPlr58mbHQ7L3RleHQmZ3Q7Jmx0Oy9jb250ZW50Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzExMCZxdW90OyBlbmQ9JnF1b3Q7MTExJnF1b3Q7Jmd0OyZsdDt0ZXh0Jmd0OwombHQ7L3RleHQmZ3Q7Jmx0Oy9jb250ZW50Jmd0OyZsdDsvcGFyYWdyYXBoJmd0OyZsdDsvc2VjdGlvbiZndDs8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 0,
            "stampName": "progressCourse",
            "stampRole": "soaSpec",
            "entity": "progressCourse"
          },
          "status": "F",
          "id": 73
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlRG9scGhpbiI+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIzIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4wPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz4xNjAwMDgwMTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuacq+aiouihgOa2suS4gOiIrDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgPC9vYmplY3Q+CiAgICA8L3ZvaWQ+CiAgICA8dm9pZCBpbmRleD0iMSI+CiAgICAgPG9iamVjdCBjbGFzcz0ib3Blbi5kb2xwaGluLmluZm9tb2RlbC5DbGFpbUl0ZW0iPgogICAgICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlIj4KICAgICAgIDxzdHJpbmc+MDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICAgICAgPHN0cmluZz5DbGFpbTAwMzwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjb2RlIj4KICAgICAgIDxzdHJpbmc+MTYwMTkxNTEwPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9Im5hbWUiPgogICAgICAgPHN0cmluZz7mnKvmoqLooYDmtrLlg4/vvIjoh6rli5XmqZ/morDms5XvvIk8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgIDwvb2JqZWN0PgogICAgPC92b2lkPgogICAgPHZvaWQgaW5kZXg9IjIiPgogICAgIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQ2xhaW1JdGVtIj4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZSI+CiAgICAgICA8c3RyaW5nPjA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlU3lzdGVtIj4KICAgICAgIDxzdHJpbmc+Q2xhaW0wMDM8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0iY29kZSI+CiAgICAgICA8c3RyaW5nPjE2MDA1NDcxMDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJuYW1lIj4KICAgICAgIDxzdHJpbmc+77yj77yy77ywPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICA8L29iamVjdD4KICAgIDwvdm9pZD4KICAgPC9hcnJheT4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZSI+CiAgIDxzdHJpbmc+NjAwPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICA8c3RyaW5nPkNsYWltMDA3PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc05hbWUiPgogICA8c3RyaW5nPuaknOafuzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0ib3JkZXJOYW1lIj4KICAgPHN0cmluZz7nlJ/nkIbjg7vlhoXoppbpj6HmpJzmn7s8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 1,
            "stampName": "末梢血液一般",
            "stampRole": "p",
            "entity": "physiologyOrder"
          },
          "status": "F",
          "id": 74
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlRG9scGhpbiI+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIyIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4wPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz4xNjAxMTg4MTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPumdnueJueeVsOeahO+8qe+9h++8peWNiuWumumHjzwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgPC9vYmplY3Q+CiAgICA8L3ZvaWQ+CiAgICA8dm9pZCBpbmRleD0iMSI+CiAgICAgPG9iamVjdCBjbGFzcz0ib3Blbi5kb2xwaGluLmluZm9tb2RlbC5DbGFpbUl0ZW0iPgogICAgICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlIj4KICAgICAgIDxzdHJpbmc+MDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICAgICAgPHN0cmluZz5DbGFpbTAwMzwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjb2RlIj4KICAgICAgIDxzdHJpbmc+MTYwMDU2MTEwPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9Im5hbWUiPgogICAgICAgPHN0cmluZz7nibnnlbDnmoTvvKnvvYfvvKXljYrlrprph4/jg7vlrprph488L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibnVtYmVyIj4KICAgICAgIDxzdHJpbmc+OTwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXJDb2RlIj4KICAgICAgIDxzdHJpbmc+MTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibnVtYmVyQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDA0PC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9InVuaXQiPgogICAgICAgPHN0cmluZz7nqK7poZ48L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgIDwvb2JqZWN0PgogICAgPC92b2lkPgogICA8L2FycmF5PgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlIj4KICAgPHN0cmluZz42MDA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgIDxzdHJpbmc+Q2xhaW0wMDc8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzTmFtZSI+CiAgIDxzdHJpbmc+5qSc5p+7PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJvcmRlck5hbWUiPgogICA8c3RyaW5nPuaknOS9k+aknOafuzwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 2,
            "stampName": "IgE",
            "stampRole": "p",
            "entity": "testOrder"
          },
          "status": "F",
          "id": 75
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlRG9scGhpbiI+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4wPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz4xNjAwOTIzMTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPu+8pe+8pu+8jeWXheijguODu+m8u+WSveiFlOODu+WJr+m8u+iFlDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgPC9vYmplY3Q+CiAgICA8L3ZvaWQ+CiAgIDwvYXJyYXk+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICA8c3RyaW5nPjYwMDwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlU3lzdGVtIj4KICAgPHN0cmluZz5DbGFpbTAwNzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NOYW1lIj4KICAgPHN0cmluZz7mpJzmn7s8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Im9yZGVyTmFtZSI+CiAgIDxzdHJpbmc+5qSc5L2T5qSc5p+7PC9zdHJpbmc+CiAgPC92b2lkPgogPC9vYmplY3Q+CjwvamF2YT4K",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 3,
            "stampName": "EF-嗅裂・鼻咽腔・副鼻腔",
            "stampRole": "p",
            "entity": "testOrder"
          },
          "status": "F",
          "id": 76
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlRG9scGhpbiI+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4wPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz4xNjAxMjI4NTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuWlvemFuOeQg++8iOm8u+axgeODu+WWgOeXsO+8iTwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgPC9vYmplY3Q+CiAgICA8L3ZvaWQ+CiAgIDwvYXJyYXk+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICA8c3RyaW5nPjYwMDwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlU3lzdGVtIj4KICAgPHN0cmluZz5DbGFpbTAwNzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NOYW1lIj4KICAgPHN0cmluZz7mpJzmn7s8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Im9yZGVyTmFtZSI+CiAgIDxzdHJpbmc+5qSc5L2T5qSc5p+7PC9zdHJpbmc+CiAgPC92b2lkPgogPC9vYmplY3Q+CjwvamF2YT4K",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 4,
            "stampName": "好酸球(鼻汁・喀痰)",
            "stampRole": "p",
            "entity": "testOrder"
          },
          "status": "F",
          "id": 77
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlTWVkIj4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW4iPgogICA8c3RyaW5nPlvnlKjms5VdIO+8keaXpe+8kuWbnuacneaYvOmjn+W+jOOBqzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW5Db2RlIj4KICAgPHN0cmluZz4wMDEwMDAyMTE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+Nzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4yPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz42MjIxNzk3MDE8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuOCquODreODkeOCv+OCuOODs+WhqemFuOWhqemMoO+8le+9je+9h+OAjOaYjuayu+OAjTwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXIiPgogICAgICAgPHN0cmluZz4yPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9Im51bWJlckNvZGUiPgogICAgICAgPHN0cmluZz4xMDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXJDb2RlU3lzdGVtIj4KICAgICAgIDxzdHJpbmc+Q2xhaW0wMDQ8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0idW5pdCI+CiAgICAgICA8c3RyaW5nPumMoDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJ5a3pLYm4iPgogICAgICAgPHN0cmluZz4xPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICA8L29iamVjdD4KICAgIDwvdm9pZD4KICAgPC9hcnJheT4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZSI+CiAgIDxzdHJpbmc+MjEyPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICA8c3RyaW5nPkNsYWltMDA3PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc05hbWUiPgogICA8c3RyaW5nPuaKleiWrCjlhoXmnI3jg7vpoJPmnI3jg7voqr/liaQpKOmZouWklik8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Im1lbW8iPgogICA8c3RyaW5nPuWGheeUqO+8iOmZouWkluWHpuaWue+8iTwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 5,
            "stampName": "オロパタジン塩酸塩錠5mg「明治」",
            "stampRole": "p",
            "entity": "medOrder"
          },
          "status": "F",
          "id": 78
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlTWVkIj4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW4iPgogICA8c3RyaW5nPlvnlKjms5VdIO+8keaXpeWPs++8kuWbnuW3pu+8kuWbnjwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW5Db2RlIj4KICAgPHN0cmluZz4wMDEwMDA1MjU8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4yPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz42MjAyMjk0MDM8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuOCr+ODreODouOCsOODquOCr+mFuO+8ru+9geeCuem8u+a2su+8ku+8heOAjOODleOCoeOCpOOCtuODvOOAjeOAgO+8ke+8me+8kO+9je+9h++8me+8ju+8le+9je+8rDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXIiPgogICAgICAgPHN0cmluZz4xPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9Im51bWJlckNvZGUiPgogICAgICAgPHN0cmluZz4xMDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXJDb2RlU3lzdGVtIj4KICAgICAgIDxzdHJpbmc+Q2xhaW0wMDQ8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0idW5pdCI+CiAgICAgICA8c3RyaW5nPueTtjwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJ5a3pLYm4iPgogICAgICAgPHN0cmluZz42PC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICA8L29iamVjdD4KICAgIDwvdm9pZD4KICAgPC9hcnJheT4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZSI+CiAgIDxzdHJpbmc+MjMyPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICA8c3RyaW5nPkNsYWltMDA3PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc05hbWUiPgogICA8c3RyaW5nPuaKleiWrCjlpJbnlKjjg7voqr/liaQpKOmZouWklik8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Im1lbW8iPgogICA8c3RyaW5nPuWklueUqO+8iOmZouWkluWHpuaWue+8iTwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 6,
            "stampName": "クロモグリク酸Na点鼻液2%「ファイザー」 190mg9.5mL",
            "stampRole": "p",
            "entity": "medOrder"
          },
          "status": "F",
          "id": 79
        },
        {
          "started": 1544494704394,
          "ended": null,
          "confirmed": 1544494704394,
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUHJvZ3Jlc3NDb3Vyc2UiPgogIDx2b2lkIHByb3BlcnR5PSJmcmVlVGV4dCI+CiAgIDxzdHJpbmc+Jmx0O3NlY3Rpb24gc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MTcmcXVvdDsmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDswJnF1b3Q7IGVuZD0mcXVvdDsyJnF1b3Q7Jmd0OyZsdDtjb21wb25lbnQgc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MSZxdW90OyBuYW1lPSZxdW90O3N0YW1wSG9sZGVyJnF1b3Q7IGNvbXBvbmVudD0mcXVvdDswJnF1b3Q7Jmd0OyZsdDsvY29tcG9uZW50Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzEmcXVvdDsgZW5kPSZxdW90OzImcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDsyJnF1b3Q7IGVuZD0mcXVvdDszJnF1b3Q7Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzImcXVvdDsgZW5kPSZxdW90OzMmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDszJnF1b3Q7IGVuZD0mcXVvdDs1JnF1b3Q7Jmd0OyZsdDtjb21wb25lbnQgc3RhcnQ9JnF1b3Q7MyZxdW90OyBlbmQ9JnF1b3Q7NCZxdW90OyBuYW1lPSZxdW90O3N0YW1wSG9sZGVyJnF1b3Q7IGNvbXBvbmVudD0mcXVvdDsxJnF1b3Q7Jmd0OyZsdDsvY29tcG9uZW50Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzQmcXVvdDsgZW5kPSZxdW90OzUmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDs1JnF1b3Q7IGVuZD0mcXVvdDs2JnF1b3Q7Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzUmcXVvdDsgZW5kPSZxdW90OzYmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDs2JnF1b3Q7IGVuZD0mcXVvdDs4JnF1b3Q7Jmd0OyZsdDtjb21wb25lbnQgc3RhcnQ9JnF1b3Q7NiZxdW90OyBlbmQ9JnF1b3Q7NyZxdW90OyBuYW1lPSZxdW90O3N0YW1wSG9sZGVyJnF1b3Q7IGNvbXBvbmVudD0mcXVvdDsyJnF1b3Q7Jmd0OyZsdDsvY29tcG9uZW50Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzcmcXVvdDsgZW5kPSZxdW90OzgmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDs4JnF1b3Q7IGVuZD0mcXVvdDs5JnF1b3Q7Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzgmcXVvdDsgZW5kPSZxdW90OzkmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDs5JnF1b3Q7IGVuZD0mcXVvdDsxMSZxdW90OyZndDsmbHQ7Y29tcG9uZW50IHN0YXJ0PSZxdW90OzkmcXVvdDsgZW5kPSZxdW90OzEwJnF1b3Q7IG5hbWU9JnF1b3Q7c3RhbXBIb2xkZXImcXVvdDsgY29tcG9uZW50PSZxdW90OzMmcXVvdDsmZ3Q7Jmx0Oy9jb21wb25lbnQmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7MTAmcXVvdDsgZW5kPSZxdW90OzExJnF1b3Q7Jmd0OyZsdDt0ZXh0Jmd0OwombHQ7L3RleHQmZ3Q7Jmx0Oy9jb250ZW50Jmd0OyZsdDsvcGFyYWdyYXBoJmd0OyZsdDtwYXJhZ3JhcGggc3RhcnQ9JnF1b3Q7MTEmcXVvdDsgZW5kPSZxdW90OzEyJnF1b3Q7Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzExJnF1b3Q7IGVuZD0mcXVvdDsxMiZxdW90OyZndDsmbHQ7dGV4dCZndDsKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzEyJnF1b3Q7IGVuZD0mcXVvdDsxNCZxdW90OyZndDsmbHQ7Y29tcG9uZW50IHN0YXJ0PSZxdW90OzEyJnF1b3Q7IGVuZD0mcXVvdDsxMyZxdW90OyBuYW1lPSZxdW90O3N0YW1wSG9sZGVyJnF1b3Q7IGNvbXBvbmVudD0mcXVvdDs0JnF1b3Q7Jmd0OyZsdDsvY29tcG9uZW50Jmd0OyZsdDtjb250ZW50IHN0YXJ0PSZxdW90OzEzJnF1b3Q7IGVuZD0mcXVvdDsxNCZxdW90OyZndDsmbHQ7dGV4dCZndDsKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzE0JnF1b3Q7IGVuZD0mcXVvdDsxNSZxdW90OyZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDsxNCZxdW90OyBlbmQ9JnF1b3Q7MTUmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDsxNSZxdW90OyBlbmQ9JnF1b3Q7MTcmcXVvdDsmZ3Q7Jmx0O2NvbXBvbmVudCBzdGFydD0mcXVvdDsxNSZxdW90OyBlbmQ9JnF1b3Q7MTYmcXVvdDsgbmFtZT0mcXVvdDtzdGFtcEhvbGRlciZxdW90OyBjb21wb25lbnQ9JnF1b3Q7NSZxdW90OyZndDsmbHQ7L2NvbXBvbmVudCZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDsxNiZxdW90OyBlbmQ9JnF1b3Q7MTcmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0Oy9zZWN0aW9uJmd0Ozwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1544494704394,
          "userModel": {
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "roles": null,
            "userId": null,
            "password": null,
            "id": 10
          },
          "karteBean": {
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "id": 26
          },
          "moduleInfoBean": {
            "stampNumber": 7,
            "stampName": "progressCourse",
            "stampRole": "pSpec",
            "entity": "progressCourse"
          },
          "status": "F",
          "id": 80
        }
      ],
      "started": 1544494704394,
      "ended": null,
      "confirmed": 1544494704394,
      "linkId": 0,
      "linkRelation": null,
      "recorded": 1544494704394,
      "userModel": {
        "memberType": null,
        "registeredDate": null,
        "licenseModel": null,
        "facilityModel": null,
        "sirName": null,
        "givenName": null,
        "commonName": "医師 二郎",
        "departmentModel": null,
        "memo": null,
        "email": null,
        "orcaId": null,
        "useDrugId": null,
        "roles": null,
        "userId": null,
        "password": null,
        "id": 10
      },
      "karteBean": {
        "patientVisits": null,
        "docInfoList": null,
        "memoList": null,
        "lastDocDate": null,
        "created": null,
        "allergies": null,
        "heights": null,
        "weights": null,
        "id": 26
      },
      "docInfoModel": {
        "hasRp": true,
        "hasTreatment": false,
        "hasLaboTest": true,
        "hasMark": false,
        "sendLabtest": false,
        "sendMml": false,
        "hasImage": false,
        "title": "耳鼻科(4/10)",
        "facilityName": null,
        "patientId": null,
        "department": "27",
        "firstConfirmDate": 1544494704394,
        "confirmDate": 1544494704394,
        "departmentDesc": "耳鼻いんこう科,27,医師 二郎,10002,JPN332020100008",
        "parentPk": 0,
        "docId": "9afe11a0ac106c2c586f49aafe7e4c86",
        "sendClaim": false,
        "versionNumber": "1.0",
        "parentIdRelation": null,
        "docType": "karte",
        "purpose": "recode",
        "healthInsurance": "31",
        "healthInsuranceDesc": "31 国家共済",
        "healthInsuranceGUID": "75923d6f-a338-4cd5-8cd1-ce60377224e0",
        "claimDate": 1544494668866,
        "patientGender": null,
        "patientName": null,
        "departmentCodeSys": null,
        "docPk": 72,
        "purposeDesc": null,
        "purposeCodeSys": null,
        "healthInsuranceCodeSys": null,
        "versionNotes": null,
        "parentId": null,
        "parentIdDesc": null,
        "parentIdCodeSys": null,
        "labtestOrderNumber": null,
        "pvthealthInsuranceModel": null,
        "createrLisence": null,
        "status": "F"
      },
      "attachment": null,
      "schema": null,
      "status": "F",
      "id": 72
    }
  ]
}
リスト3.カルテ要求&返送


これは、クライアントのカルテ要求に対するサーバのカルテ返送だと思われる。
1行目のRESTful APIでクライアントはid=72のカルテ(document)をサーバに要求している。この72という値はセッション1のサーバからのレスポンスJSONデータの中に「docPk」という属性で含まれていた。おそらくこれを要求したのであろう。

これに対してサーバは非常に長いメッセージを返している。 このメッセージの構造を見てみると、リスト4に示す枠組みからなっている。
{
    "list": [
        {
            "modules": [
                {...①...},
                {...②...},
                {...③...},
                {...④...},
                {...⑤...},
                {...⑥...},
                {...⑦...},
                {...⑧...}
            ],
            "started": 1544494704394,
            "ended": null,
            "confirmed": 1544494704394,
            "linkId": 0,
            "linkRelation": null,
            "recorded": 1544494704394,
            "userModel": {...⑨...},
            "karteBean": {...⑩...},
            "docInfoModel": {...⑪...},
            "attachment": null,
            "schema": null,
            "status": "F",
            "id": 72
        }
    ]
}
リスト4. カルテの構造 

2018年12月5日水曜日

実験

ネットワーク構成図


VPNサーバが構築できたところで実験を行う。実験に使用するネットワークの構成図を図1に示す。

図1.ネットワーク構成図

Windowsパソコン2台(A, Bとする)とルータ R 及びリピータハブ H を準備する。ルータ R のインターネット側を学内LANに接続する。ルータ R のLAN側にはリピータハブ H を接続し、そのリピータハブ H からパソコンA、Bに接続する。

その際、ルータ R にはもともとパソコンAに振られていたIPアドレスとサブネットマスク、デフォルトゲートウェイ、DNSサーバのIPアドレスを設定する。そして、パソコンA、BはルータRのDHCP機能を利用してIPアドレスを自動取得できるように設定する。

VPNを使わないときのパケットキャプチャ


最初にVPNを使わないときのパソコンAとサーバSの通信を、パソコンBでWiresharkを使ってキャプチャする。
手順は以下のとおりである。
  1. パソコンAでORCAクライアントを起動し、ORCAにログインする。
  2. パソコンAで[01 医事業務]→[12 登録]と進んで患者登録画面を出す。
  3. キャプチャフィルタにサーバ S のIPアドレスを指定(host [サーバSのIPアドレス])して パソコンBでWiresharkを開始する。
  4. パソコンAで登録済の患者番号を入力してENTERキーをクリックする。
  5. パソコンBのパケットキャプチャを停止し、パケット一覧からプロトコルがTCPのパケットを選択して、メニューから[Analyze]を選び[Follow]→[TCP Stream]と選択してパケットを再構築する。
  6. 画面下の[Show and save data as]から[UTF-8]を選択して、患者情報が丸見えであることを確認する。

VPNを使ったときのパケットキャプチャ


次に、VPNを使った場合のパソコンAとサーバSの通信を、パソコンBでWiresharkを使ってキャプチャする。

手順は以下のとおりである。
  1. パソコンAでVPNクライアント接続マネージャを立ち上げてVPNサーバ S に接続する。
  2. ORCAクライアントを起動し、ORCAにログインする。
  3. パソコンAで[01 医事業務]→[12 登録]と進んで患者登録画面を出す。
  4. キャプチャフィルタにサーバ S のIPアドレスを指定(host [サーバSのIPアドレス])して パソコンBでWiresharkを開始する。
  5. パソコンAで登録済の患者番号を入力してENTERキーをクリックする。
  6. パソコンBのパケットキャプチャを停止し、パケット一覧からプロトコルがTCPのパケットを選択して、メニューから[Analyze]を選び[Follow]→[TCP Stream]と選択してパケットを再構築する。
  7. 画面下の[Show and save data as]から[UTF-8]を選択して、VPNを使わなかった場合のキャプチャデータと比べる。 


キャプチャ結果


キャプチャ結果を以下に示す。

VPNを使わなかった場合


図2.VPNなしの場合の患者情報キャプチャデータ


VPNを使った場合


図3.VPNありの場合の患者情報キャプチャデータ



VPN(サーバインストール版)

今までSoftEther VPN ServerをDockerコンテナで実現する方法を試してきたが、うまくいかなかった。うまくいかなかったというのは、仮想NICと物理NICの両方を仮想ブリッジにブリッジさせたけれど、VPNクライアントから接続するとVPNサーバ本体で稼働するサービス(たとえばsshなど)には接続できたものの、サーバの物理NICが接続しているローカルネット上の他のホストと通信できなかったという意味である。

そこで、Dockerコンテナ版のSoftEther VPN Serverをやめて、サーバ本体にSoftEther VPN Serverをインストールしてみる。

SoftEther VPN Serverのインストール


SoftEther VPN Serverのインストールは、公式サイトの「VPN Serverの導入」に従って行う。

まず、SoftEtherダウンロードセンターからSoftEther VPN Serverパッケージをダウンロードする。


図1.SoftEther VPN Serverのダウンロードサイト

図1に示すように、[ダウンロードするソフトウェアを選択]には「SoftEther VPN (Freeware)」を、[コンポーネントを選択]には「SoftEther VPN Server」を、[プラットフォームを選択]には「Linux」を、[CPUを選択]には「Intel x64 / AMD64 (64bit)」を選択する。すると、ダウンロード可能なパッケージの一覧が表示されるので、その中から先頭にある下記のパッケージをダウンロードする。
softether-vpnserver-v4.28-9669-beta-2018.09.11-linux-x64-64bit.tar.gz
なお、 上記のパッケージで「v4.28-9669-beta-2018.09.11」の部分はバージョンによって異なる。

ダウンロードしたパッケージをWinSCPを使ってUbuntuサーバのユーザのホームディレクトリ(/home/hinfo/)へアップロードする(ユーザIDはhinfoを使用するものとする)。以降はインストールマニュアルに従ってインストール作業を行う。

まず、Teratermを使ってユーザhinfoでUbuntuサーバへログインする。「ls」コマンドを入力すると、図2に示すように、WinSCPでアップロードしたSoftEther VPN Serverのパッケージがユーザhinfoのホームディレクトリ(/home/hinfo/)上にあることが確認できる。

図2.UbuntuサーバにアップロードされたSoftEther VPN Serverのインストールファイル

次に、tarコマンドを使ってパッケージを解凍する。
hinfo@orca17:~$ sudo tar xzvf softether-vpnserver-v4.28-9669-beta-2018.09.11-linux-x64-64bit.tar.gz
[sudo] hinfo のパスワード:
vpnserver/
vpnserver/Makefile
vpnserver/.install.sh
vpnserver/ReadMeFirst_License.txt
vpnserver/Authors.txt
vpnserver/ReadMeFirst_Important_Notices_ja.txt
vpnserver/ReadMeFirst_Important_Notices_en.txt
vpnserver/ReadMeFirst_Important_Notices_cn.txt
vpnserver/code/
vpnserver/code/vpnserver.a
vpnserver/code/vpncmd.a
vpnserver/lib/
vpnserver/lib/libcharset.a
vpnserver/lib/libcrypto.a
vpnserver/lib/libedit.a
vpnserver/lib/libiconv.a
vpnserver/lib/libintelaes.a
vpnserver/lib/libncurses.a
vpnserver/lib/libssl.a
vpnserver/lib/libz.a
vpnserver/lib/License.txt
vpnserver/hamcore.se2
hinfo@orca17:~$
リスト1.パッケージの解凍

パッケージを解凍すると「vpnserver」という新しいディレクトリが作成される。cdコマンドを使ってこのディレクトリへ入り、「make」と入力する(リスト2)。
hinfo@orca17:~$ cd vpnserver/
hinfo@orca17:~/vpnserver$ sudo make
--------------------------------------------------------------------

SoftEther VPN Server (Ver 4.28, Build 9669, Intel x64 / AMD64) for Linux Install Utility
Copyright (c) SoftEther Project at University of Tsukuba, Japan. All Rights Reserved.

--------------------------------------------------------------------


Do you want to read the License Agreement for this software ?

 1. Yes
 2. No

Please choose one of above number:
リスト2.「使用権許諾契約書を読みますか?」という内容の質問

リスト2で1を選択すると、画面にたくさんの文字が流れて次のような表示が出る。
Did you read and understand the License Agreement ?
(If you couldn't read above text, Please read 'ReadMeFirst_License.txt'
 file with any text editor.)

 1. Yes
 2. No

Please choose one of above number:
リスト3.「使用権許諾契約書を読みましたか?」という内容の質問

リスト3で1を選択すると、次の表示が出る。
Did you agree the License Agreement ?

1. Agree
2. Do Not Agree

Please choose one of above number:
リスト4.「使用権許諾契約書に同意しますか?」という内容の質問

 リスト4で1を選択するとインストールが始まり、次のような画面が出ればプログラムの生成は成功である。
--------------------------------------------------------------------
The preparation of SoftEther VPN Server is completed !


*** How to switch the display language of the SoftEther VPN Server Service ***
SoftEther VPN Server supports the following languages:
  - Japanese
  - English
  - Simplified Chinese

You can choose your prefered language of SoftEther VPN Server at any time.
To switch the current language, open and edit the 'lang.config' file.


*** How to start the SoftEther VPN Server Service ***

Please execute './vpnserver start' to run the SoftEther VPN Server Background Service                                                                        .
And please execute './vpncmd' to run the SoftEther VPN Command-Line Utility to config                                                                        ure SoftEther VPN Server.

Of course, you can use the VPN Server Manager GUI Application for Windows / Mac OS X                                                                         on the other Windows / Mac OS X computers in order to configure the SoftEther VPN Ser                                                                        ver remotely.


*** For Windows users ***
You can download the SoftEther VPN Server Manager for Windows
from the http://www.softether-download.com/ web site.
This manager application helps you to completely and easily manage the VPN server ser                                                                        vices running in remote hosts.


*** For Mac OS X users ***
In April 2016 we released the SoftEther VPN Server Manager for Mac OS X.
You can download it from the http://www.softether-download.com/ web site.
VPN Server Manager for Mac OS X works perfectly as same as the traditional Windows ve                                                                        rsions. It helps you to completely and easily manage the VPN server services running                                                                         in remote hosts.

--------------------------------------------------------------------

make[1]: ディレクトリ '/home/hinfo/vpnserver' から出ます
hinfo@orca17:~/vpnserver$
リスト5.VPNサーバ生成処理


VPNサーバの配置


VPNサーバプログラムの生成が完了したら、VPNプログラムを/usr/local/ディレクトリへ配置する。
>hinfo@orca17:~/vpnserver$ cd ..
hinfo@orca17:~$ sudo mv vpnserver/ /usr/local/
hinfo@orca17:~$ cd /usr/local/
hinfo@orca17:/usr/local$ ls
bin  etc  games  include  lib  man  sbin  share  site-jma-receipt  src  vpnserver

リスト6.VPNサーバの配置 

 リスト6に示すように、/usr/local/ディレクトリ内にvpnserverがあれば配置は完了である。

パーミッションの変更


この vpnserver ディレクトリ内のファイルを、「root 権限」でなければ読み書きすることができないように、パーミッションを「600」に変更する。
「600」というのは、所有者(この場合は管理者であるroot)に対してのみ「rw-」、すなわち「読む」「書く」権限を与えるという意味である。
hinfo@orca17:~$ cd /usr/local/vpnserver/
hinfo@orca17:/usr/local/vpnserver$ sudo chmod 600 *
hinfo@orca17:/usr/local/vpnserver$ sudo chmod 700 vpncmd
hinfo@orca17:/usr/local/vpnserver$ sudo chmod 700 vpnserver
hinfo@orca17:/usr/local/vpnserver$ ls -l
合計 10480
-rw------- 1 root root    2955  9月 11 12:35 Authors.txt
-rw------- 1 root root    3010  9月 11 12:35 Makefile
-rw------- 1 root root   30801  9月 11 12:35 ReadMeFirst_Important_Notices_cn.txt
-rw------- 1 root root   36296  9月 11 12:35 ReadMeFirst_Important_Notices_en.txt
-rw------- 1 root root   50695  9月 11 12:35 ReadMeFirst_Important_Notices_ja.txt
-rw------- 1 root root   58903  9月 11 12:35 ReadMeFirst_License.txt
drw------- 2 root root    4096 12月  5 09:37 chain_certs
drw------- 2 root root    4096 12月  5 09:37 code
-rw------- 1 root root 1296639  9月 11 12:35 hamcore.se2
-rw------- 1 root root     867 12月  5 09:37 lang.config
drw------- 2 root root    4096 12月  5 09:37 lib
-rwx------ 1 root root 4611944 12月  5 09:37 vpncmd
-rwx------ 1 root root 4612024 12月  5 09:37 vpnserver
hinfo@orca17:/usr/local/vpnserver$
リスト7.パーミッションの変更

なお、vpncmdとvpnserverは実行権を与えるためにパーミッションを「700」にしている。ここで、「700」は、所有者にのみ「rwx」、すなわち「読む」「書く」「実行する」権限を与えるという意味である。

動作チェック



これでインストールが完了したのでvpncmd の check コマンドによる動作チェックを行う。

まず、cdコマンドを使ってディレクトリ「/usr/local/vpnserver/」に入って管理者権限でvpncmdを入力する。
hinfo@orca17:/usr/local/vpnserver$ cd /usr/local/vpnserver/
hinfo@orca17:/usr/local/vpnserver$ sudo ./vpncmd
vpncmd コマンド - SoftEther VPN コマンドライン管理ユーティリティ
SoftEther VPN コマンドライン管理ユーティリティ (vpncmd コマンド)
Version 4.28 Build 9669   (Japanese)
Compiled 2018/09/11 12:23:27 by yagi at pc33
Copyright (c) SoftEther VPN Project. All Rights Reserved.

vpncmd プログラムを使って以下のことができます。

1. VPN Server または VPN Bridge の管理
2. VPN Client の管理
3. VPN Tools コマンドの使用 (証明書作成や通信速度測定)

1 - 3 を選択:
リスト8.動作チェック

すると、リスト8に示す画面になるので、「3. VPN Tools コマンドの使用 (証明書作成や通信速度測定)」を選択する。すると「VPN Tools を起動しました。HELP と入力すると、使用できるコマンド一覧が表示できます。」と表示されるので、「check」コマンドを実行する。
1 - 3 を選択: 3

VPN Tools を起動しました。HELP と入力すると、使用できるコマンド一覧が表示できま す。

VPN Tools>check
Check コマンド - SoftEther VPN の動作が可能かどうかチェックする
---------------------------------------------------
SoftEther VPN 動作環境チェックツール

Copyright (c) SoftEther VPN Project.
All Rights Reserved.

この動作環境チェックツールを実行したシステムがテストに合格した場合は、SoftEther VPN ソフトウェアが動作する可能性が高いです。チェックにはしばらく時間がかかる場合があります。そのままお待ちください...

'カーネル系' のチェック中...
              [合格] ○
'メモリ操作系' のチェック中...
              [合格] ○
'ANSI / Unicode 文字列処理系' のチェック中...
              [合格] ○
'ファイルシステム' のチェック中...
              [合格] ○
'スレッド処理システム' のチェック中...
              [合格] ○
'ネットワークシステム' のチェック中...
              [合格] ○

すべてのチェックに合格しました。このシステム上で SoftEther VPN Server / Bridge  が正しく動作する可能性が高いと思われます。

コマンドは正常に終了しました。

VPN Tools>
リスト9.「check」コマンド

リスト9に示すように「コマンドは正常に終了しました」と出れば動作確認は完了である。「exit」を入力してvpncmdを終了させる。

スタートアップスクリプト


VPN Serverのスタートアップスクリプトは 、公式サイトに例示されているものではなく、参考サイトに書かれてあるものを使う。
これは、スタートアップスクリプト内でtapデバイス(tap_vlan)を仮想ブリッジ(br0)にブリッジさせるスクリプトを使うためである。viコマンドを使ってディレクトリ「/etc/init.d/」内に「vpnserver」というファイルを作成し、リスト10に示すスタートアップスクリプトを書き込んで保存する。
hinfo@orca17:~$ cd /etc/init.d
hinfo@orca17:/etc/init.d$ sudo vi vpnserver
リスト10./etc/init.d/内にスタートアップスクリプト「vpnserver」を作成する
#!/bin/sh
### BEGIN INIT INFO
# Provides:                 vpnserver
# Required-Start:           $local_fs $network
# Required-Stop:            $local_fs $network
# Default-Start:            2 3 4 5
# Default-Stop:             0 1 6
# Short-Description:        SoftEther VPN
# Description:              Start vpnserver daemon SoftEther VPN Server
### END INIT INFO
  
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/subsys/vpnserver
  
. /lib/lsb/init-functions
  
test -x $DAEMON || exit 0
  
case "$1" in
start)
sleep 3
log_daemon_msg "Starting SoftEther VPN Server" "vpnserver"
$DAEMON start >/dev/null 2>&1
touch $LOCK
log_end_msg 0
sleep 3
  
# SoftEther VPNで追加した仮想tapデバイス名を調べる
tap=`/sbin/ifconfig -a| awk '$1 ~ /^tap/ {print $1}'`
/sbin/brctl addif br0 $tap
;;
  
stop)
log_daemon_msg "Stopping SoftEther VPN  Server" "vpnserver"
$DAEMON stop >/dev/null 2>&1
rm $LOCK
log_end_msg 0
sleep 2
  
;;
  
restart)
$DAEMON stop
sleep 2
  
$DAEMON start
sleep 5
# SoftEther VPNで追加した仮想tapデバイス名を調べる
tap=`/sbin/ifconfig -a| awk '$1 ~ /^tap/ {print $1}'`
/sbin/brctl addif br0 $tap
;;
  
status)
    if [ -e $LOCK ]
    then
        echo "vpnserver is running."
    else
        echo "vpnserver is not running."
    fi
;;
*)
  
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0 
リスト11.スタートアップスクリプト「/etc/init.d/vpnserver」の内容

なお、仮想ブリッジ「br0」は、前回のブログの「リスト3./etc/network/interfacesの編集」によってシステム起動時に作成される。

その後、作成したスタートアップスクリプトに実行権限を与える。
hinfo@orca17:/etc/init.d$ sudo chmod 755 vpnserver
リスト12.スタートアップスクリプトのパーミッションの変更

次いで下記のコマンドを入力して作成したスタートアップスクリプトを有効化する。
hinfo@orca17:~$ sudo systemctl enable vpnserver
[sudo] hinfo のパスワード:
vpnserver.service is not a native service, redirecting to systemd-sysv-install
Executing /lib/systemd/systemd-sysv-install enable vpnserver
hinfo@orca17:~$ sudo /lib/systemd/systemd-sysv-install enable vpnserver
hinfo@orca17:~$ ls -l /etc/rc*.d/ | grep vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 K01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 K01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 S01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 S01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 S01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 S01vpnserver -> ../init.d/vpnserver
lrwxrwxrwx 1 root root  19 12月  5 12:14 K01vpnserver -> ../init.d/vpnserver
hinfo@orca17:~$
リスト12.スタートアップスクリプトの有効化

これによってディレクトリ/etc/rc*.d/内にスタートアップスクリプト/etc/init.d/vpnserverへのシンボリックリンクが作られる。

次に、vpnserverを起動する。
hinfo@orca17:~$ sudo systemctl start vpnserver
Warning: vpnserver.service changed on disk. Run 'systemctl daemon-reload' to reload units.
リスト13.vpnserverの起動

vpnserverのログは/usr/local/vpnserver/server_log/というディレクトリ内に「vpn_YYYYMMDD.log」という名前で作成される(YYYYMMDDは西暦年月日)。エラーが発生した場合はこのログファイルに何らかのメッセージが表示されるので確認すればよい。

サーバ管理マネージャを使った接続設定

WindowsパソコンにSoftEther VPN サーバ管理マネージャをインストールして、サーバの設定を行う。

サーバ管理マネージャのダウンロードとインストール

SoftEtherのダウンロードセンターからサーバ管理マネージャをダウンロードする。


図3.サーバ管理マネージャのダウンロードサイト
図3に示すように、[ダウンロードするソフトウェアを選択]には「SoftEther VPN (Freeware)」を、[コンポーネントを選択]には「SoftEther VPN Server Manager for Windows」を、[プラットフォームを選択]には「Windows」を、[CPUを選択]には「Intel (x86 and x64)」を選択する。すると、ダウンロード可能なパッケージの一覧が表示されるので、その中から先頭にある下記のパッケージをダウンロードする。
SoftEther VPN Server and VPN Bridge (Ver 4.28, Build 9669, beta)
なお、 上記のパッケージで「Ver 4.28, Build 9669, beta」の部分はバージョンによって異なる。

ダウンロードが完了したらファイルをダブルクリックしてインストールを開始する。なお、インストールするソフトウェアの選択では「SoftEther VPN Server サーバ管理マネージャ(管理ツールのみ)」を選択する。

図4.インストールするソフトウェアの選択


サーバの設定


インストールが完了したらサーバー管理マネージャを起動する。

図5.サーバー管理マネージャ

図5で[新しい接続設定]をクリックする。

図6.新しい接続設定

[接続設定名]に「******への接続設定」(******は各グループのホスト名:例:orca11)、[ホスト名]にはサーバのIPアドレスを入力して[OK]をクリックする。なお、この段階ではまだ[管理パスワード]は入力しない

図7.接続設定が登録された

図7に戻ると一覧に先ほど登録した接続設定名が表示されるので、これを選んで[接続]ボタンをクリックする。すると、図8に示すパスワード入力画面が表示される。

図8.パスワード入力画面

ここで、サーバー管理マネージャの管理者パスワードを設定して[OK]ボタンを押す。「パスワードを変更しました」と表示されたら[OK]ボタンを押す。すると、図9に示すVPNサーバの種類を選択する画面が表示される。

図9.簡易セットアップ画面(VPNサーバの種類)

ここでは[リモートアクセスVPNサーバ]にチェックを入れて[次へ]進む。すると「続行すると、このVPN ServerまたはVPN Bridgeの現在の設定内容は、簡易セットアップで指定した内容に初期化されます。よろしいですか?」と表示されるので、そのまま[はい]をクリックする。

次に、図10に示すように[仮想HUB]を入力する画面が出るので「VPN-******」と入力して[OK]ボタンをクリックする。ここで、「******」の部分は各グループのホスト名とする。

図10.仮想HUB名の決定

 次に図11に示すダイナミックDNSの設定画面が表示される。ここでは[ダイナミックDNSホスト名の変更]に各グループのホスト名を入力して[上記のDNSホスト名に変更する]をクリックする。このとき、画面左下に[DNS鍵]が表示されるのでノートに書き写しておく(スマホで写真を撮っておいてもよい)。

図11.ダイナミックDNS機能

 確認画面が出たら[OK]ボタンを押すと「IPsec / L2TP / EtherIP / L2TPv3 サーバー機能の設定」画面が出る(図12)。ここでは[L2TPサーバー機能を有効にする(L2TP over IPsec)]にチェックをつけ、[IPsec事前共有鍵]にサーバのパスワードを入力して[OK]ボタンをクリックする。


図12.IPsec / L2TP / EtherIP / L2TPv3 サーバー機能の設定

 次に図13に示すVPN Azureの設定画面が表示されるが、ここでは[VPN Azureを無効にする]をチェックして[OK]ボタンをクリックする。


図13.VPN Azure 設定画面

次に図14に示すユーザ作成画面が表示されるので[ユーザーを作成する]をクリックする。

図14.ユーザの作成

[ユーザーの新規作成]画面が出たら[ユーザ名]には「hinfo」を、パスワードには「●●●●●●●●」を入力して[OK]ボタンをクリックする。

図15.新規ユーザー作成画面

 「ユーザhinfoを作成しました。」と確認メッセージが出るので[OK]ボタンを押すと、図16に示す[ユーザの管理]画面が表示されるので[閉じる]ボタンを押す。

図16.ユーザ管理画面
 図17の画面に戻ったら[ローカルブリッジ設定]ボタンをクリックする。

図17.サーバ管理マネージャ

すると、図18に示す画面が表示される。

図18.ローカルブリッジ設定

ここで、[仮想HUB]には図10で入力した「VPN-******」(******はサーバのコンピュータ名)を入力し、[作成する種類]は「新しい tap デバイスとのブリッジ接続」をチェックし、[新しい tap デバイス名]には「vlan」と入力して[ローカルブリッジを追加]をクリックする。


図19.VM内でのローカルブリッジ機能の使用

図19に示す画面が出てくるので[OK]ボタンを押すと「ローカルブリッジ接続の定義を追加しました」と表示される。ここで[OK]ボタンを押すと設定作業は完了して図20が現れる。

図20.ローカルブリッジ設定完了

画面上部に仮想HUB名「VPN-******」(******はサーバのホスト名)とtapデバイス名「vlan」が表示されていれば成功である。

VPNサーバ起動


ここまで終えたらシステムを再起動する。
再起動後、"ip a"コマンドを使って「tap_vlan」というインターフェースが作成されていることを確認する。
hinfo@orca17:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
    link/ether f4:4d:30:6b:ac:0c brd ff:ff:ff:ff:ff:ff
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 5e:a8:7e:4d:dd:13 brd ff:ff:ff:ff:ff:ff
    inet 172.16.111.217/16 brd 172.16.255.255 scope global br0
       valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:72:4b:1c:a2 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
6: veth77254f2@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 52:9c:a9:ed:62:13 brd ff:ff:ff:ff:ff:ff link-netnsid 0
8: veth00fc6a7@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether ca:57:e8:b0:d0:67 brd ff:ff:ff:ff:ff:ff link-netnsid 1
10: tap_vlan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN group default qlen 1000
    link/ether 5e:a8:7e:4d:dd:13 brd ff:ff:ff:ff:ff:ff
hinfo@orca17:~$
リスト13.インターフェース一覧

リスト13を見ると、物理NIC「enp3s0」と仮想NIC(tap_vlan)が仮想ブリッジ「br0」にブリッジされていることがわかる。
同様に、 仮想NIC「veth77254f2@if5」と「veth00fc6a7@if7」が仮想ブリッジ「docker0」にブリッジしていることがわかる。これはDockerで利用されている。

これは、リスト14に示すようにbrctlコマンドを使って確認できる。
hinfo@orca17:~$ sudo brctl show
[sudo] hinfo のパスワード:
bridge name     bridge id               STP enabled     interfaces
br0             8000.5ea87e4ddd13       no              enp3s0
                                                        tap_vlan
docker0         8000.0242724b1ca2       no              veth00fc6a7
                                                        veth77254f2
hinfo@orca17:~$
リスト14.brctlコマンドでブリッジを確認 


接続テスト


接続テストを行うためにクライアントパソコンに SoftEther VPN Client for Windows をインストールしてVPNサーバと接続するように設定する。
これについては、ブログ「VPN(Docker版) 」の「SoftEther VPN クライアントからの接続」に書いた。

参考サイト

  1. CuBox-i/HummingBoard(22) SoftEther VPNで外から irMagician を制御してエアコンをつける
  2. SoftEther VPN

【Tips】


スタートアップスクリプトのLSB記法


/etc/init.dに格納するスタートアップスクリプトにはchkconfig用とLSB記法の2通りがある。chkconfigはRedHat系専用で、LSB記法はLinuxの標準記法のため、ディストリビューションによらず利用できる。また、両方書くとLSB記法が使用される。
 

仮想NICの作成


ブログ「VPN(Docker版)」の「VPNサーバ上で稼働するサービスへの接続」 では、仮想NICを作るのにvpncmdを使った。
しかし、これは図18でtapデバイスを作成することと同じことなので必要ない。
vpncmdはサーバ管理マネージャと同等な機能をCUIで提供しているに過ぎない。
下記にその一例としてvpncmdを使ってtapデバイスを表示しているところを示す。
root@orca17:/home/hinfo# /usr/local/vpnserver/vpncmd  localhost:443 /SERVER
vpncmd コマンド - SoftEther VPN コマンドライン管理ユーティリティ
SoftEther VPN コマンドライン管理ユーティリティ (vpncmd コマンド)
Version 4.28 Build 9669   (Japanese)
Compiled 2018/09/11 12:23:27 by yagi at pc33
Copyright (c) SoftEther VPN Project. All Rights Reserved.

パスワード: *******

VPN Server "localhost" (ポート 443) に接続しました。

VPN Server 全体の管理権限があります。

VPN Server>BridgeList
BridgeList コマンド - ローカルブリッジ接続の一覧の取得
番号|仮想 HUB 名|ブリッジ先 LAN カードまたは tap デバイス名|状態
----+-----------+------------------------------------------+------
1   |VPN-****** |vlan                                      |動作中
コマンドは正常に終了しました。

VPN Server>

OpenDolphinとORCAの連携

第3章の章末問題 第2章の章末問題でやったカルテ例1をOpenDolphinに入力してORCAで診療報酬明細書を作成し、模範解答と比較しなさい。 を実際にやってみたのでまとめておく。 OpenDolphinで過去にさかのぼってカルテは作成できるか? その前に標題に...